diff --git a/.babelrc b/.babelrc index 5abbaef10..589a4772e 100644 --- a/.babelrc +++ b/.babelrc @@ -4,7 +4,7 @@ "@babel/preset-typescript", [ "@babel/preset-env", { "targets": { - "node": "14" + "node": "16" }, "modules": "commonjs" } ] @@ -14,7 +14,8 @@ [ "babel-plugin-module-resolver", { "root": [ "./src" ], "alias": { - "@engine": "./dist/game-engine", + "@engine": "./dist/engine", + "@server": "./dist/server", "@plugins": "./dist/plugins" } } ] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 956a4c457..01c1b4928 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Lint & Build Project on: pull_request: - branches: [ master, develop ] + branches: [ master, develop, feature/** ] push: branches: [ master, develop ] @@ -25,5 +25,8 @@ jobs: - name: Run Linter run: npm run lint + - name: Run Typecheck + run: npm run typecheck + - name: Build Project run: npm run build diff --git a/.gitignore b/.gitignore index d7fded1a9..16d91b3a4 100644 --- a/.gitignore +++ b/.gitignore @@ -18,10 +18,11 @@ yarn-error.log* # Editor directories.ts and files .idea -.vscode *.suo *.ntvs* *.njsproj *.sln *.sw? /.vs + +/coverage/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..1ec61fe7b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.tabSize": 4, + "files.trimTrailingWhitespace": true, + "files.trimFinalNewlines": true, + "files.insertFinalNewline": true +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 78cbe7450..2f5cae3e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,3 +35,44 @@ We do have a few coding styles and lint rules we'd like all contributors to adhe - Use TypeScript getters/setters instead of specific getter/setter methods - `public get myVar(): number` instead of `public getMyVar(): number` - `public set myVar(myVar: number)` instead of `public setMyVar(myVar: number)` + +## Testing + +Unit tests can be written using Jest. To execute the test suite, run `npm test` + +- Test files should be located next to the file under test, and called `file-name.test.ts` +- Tests should use the `when / then` pattern made up of composable `describe` statements +- Make use of `beforeEach` to set up state before each test + +After running the tests, you can find code coverage in the `./coverage/` folder. + +### When / Then testing pattern + +Tests should be broken down into a series of `describe` statements, which set up their own internal state when possible. + +```ts +describe('when there is a player', () => { + let player: Player + + beforeEach(() => { + player = createMockPlayer() + }) + + describe('when player is wearing a hat', () => { + beforeEach(() => { + player.equipment().set(0, someHatItem) + }) + + test('should return true', () => { + const result = isWearingHat(player) + + expect(result).toEqual(true) + }) + }) +}) +``` + +There are two main benefits to this kind of design: + +- It serves as living documentation: from reading the `beforeEach` block you can clearly see how the prerequisite of "player is wearing a hat" is achieved +- It allows for easy expansion of test cases: future developers can add further statements inside "when player is wearing a hat" if they want to make use of that setup \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 68b77235b..cc07b52b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,15 @@ -FROM node:14 +FROM node:16 WORKDIR /usr/src/app COPY package.json ./ COPY package-lock.json ./ -RUN npm install +RUN npm ci COPY src ./src COPY tsconfig.json ./ +COPY .babelrc ./ -RUN npm build +RUN npm run build EXPOSE 43594 -CMD [ "npm", "start" ] +CMD [ "npm", "run", "start:standalone" ] diff --git a/README.md b/README.md index a9cdf07c3..91a2c8996 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -![RuneJS](https://i.imgur.com/pmkdSfc.png) +[![RuneJS Discord Server](https://img.shields.io/discord/678751302297059336?label=RuneJS%20Discord&logo=discord)](https://discord.gg/5P74nSh) -# RuneJS +[![RuneJS](https://i.imgur.com/QSXNzwC.png)](https://github.com/runejs/) -[![RuneJS Discord Server](https://img.shields.io/discord/678751302297059336?label=RuneJS%20Discord&logo=discord)](https://discord.gg/5P74nSh) +# RuneJS Game Server -RuneJS is a RuneScape game server written entirely using TypeScript and JavaScript. The aim of this project is to create a game server that is both fun and easy to use, while also providing simple content development systems. +RuneJS is a RuneScape game server written in TypeScript and JavaScript. The aim of this project is to create a game server that is both fun and easy to use, while also providing simple content development systems. -The server runs on the 435 revision of the game, which was a game update made on October 31st, 2006. There are not any plans to convert it to other versions at this time. +The game server currently runs a build of RuneScape from October 30th-31st, 2006 (game build #435). No other builds are supported at this time, but may become available in the future. **RuneJS is completely open-source and open to all pull requests and/or issues. Many plugins have been added by contributor pull requests and we're always happy to have more!** @@ -14,24 +14,16 @@ The server runs on the 435 revision of the game, which was a game update made on ## Setup -1. Download and install NodeJS **version 14 or higher**: https://nodejs.org/en/ -2. Clone the Github Repo: https://github.com/runejs/server -3. Install dependencies by navigating to the project in your Terminal or command prompt and running the command npm install -4. Copy the `data/config/server-config.example.yaml` and paste it into the same folder using the name `server-config.yaml` -5. Go into your new `server-config.yaml` file and modify your RSA modulus and exponent with the ones matching your game client - - You may also modify the server's port and host address from this configuration file -6. Run the game server with `npm start` - -The game server will spin up and be accessible via port 43594. +### Prerequisites -### Setup using docker +- [`docker`](https://docs.docker.com/get-docker/) and [`docker-compose`](https://docs.docker.com/compose/install/) + - If on Windows, `docker-compose` comes with `docker` -1. Download and install Docker and Docker Compose: first https://docs.docker.com/get-docker/ then https://docs.docker.com/compose/install/ -2. Copy the `config/server-config.example.yaml` and paste it into the same folder using the name `server-config.yaml` -3. Go into your new `server-config.yaml` file and modify your RSA modulus and exponent with the ones matching your game client +1. Copy the `config/server-config.example.json` and paste it into the same folder using the name `server-config.json` +2. Go into your new `server-config.json` file and modify your RSA modulus and exponent with the ones matching your game client - You may also modify the server's port and host address from this configuration file -4. Build the docker image with `docker-compose build` -5. Run the game server with `docker-compose up' +3. Build the docker image with `docker-compose build` +4. Run the game server with `docker-compose up' The game server will spin up and be accessible via port 43594. @@ -40,12 +32,18 @@ The game server will spin up and be accessible via port 43594. The [RuneScape Java Client #435](https://github.com/runejs/refactored-client-435) must be used to log into a RuneJS game server. ## Additional Commands -* `npm run start:game` Launches the game server by itself without building -* `npm run start:game:dev` Builds and launches the game server by itself in watch mode -* `npm run start:login` Launches the login server by itself without building -* `npm run start:update` Launches the update server by itself without building -* `npm run start:infra` Launches both the login and update server without building -* `npm run start:standalone` Launches all three servers concurrently without building + +Before running these commands, you must: + +1. have [NodeJS **version 16 or higher**](https://nodejs.org/en/) installed on your machine +2. run `npm install` from the root of this project + +* `npm run game` Launches the game server by itself without building +* `npm run game:dev` Builds and launches the game server by itself in watch mode +* `npm run login` Launches the login server by itself without building +* `npm run update` Launches the update server by itself without building +* `npm run infra` Launches both the login and update server without building +* `npm run standalone` Launches all three servers concurrently without building * `npm run build:watch` Builds the application and watches for changes * `npm run build` Builds the application * `npm run lint` Runs the linter against the codebase to look for code style issues diff --git a/config/server-config.example.json b/config/server-config.example.json index 87201f24e..738feb413 100644 --- a/config/server-config.example.json +++ b/config/server-config.example.json @@ -12,6 +12,7 @@ "loginServerPort": 43591, "rsaMod": "119568088839203297999728368933573315070738693395974011872885408638642676871679245723887367232256427712869170521351089799352546294030059890127723509653145359924771433131004387212857375068629466435244653901851504845054452735390701003613803443469723435116497545687393297329052988014281948392136928774011011998343", "rsaExp": "12747337179295870166838611986189126026507945904720545965726999254744592875817063488911622974072289858092633084100280214658532446654378876853112046049506789703022033047774294965255097838909779899992870910011426403494610880634275141204442441976355383839981584149269550057129306515912021704593400378690444280161", + "encryptionEnabled": true, "playerSavePath": "./data/saves", "showWelcome": true, diff --git a/data/config/items/equipment/standard-metals/adamant-armour.json b/data/config/items/equipment/standard-metals/adamant-armour.json index e4c5abe63..e14fc38a8 100644 --- a/data/config/items/equipment/standard-metals/adamant-armour.json +++ b/data/config/items/equipment/standard-metals/adamant-armour.json @@ -9,7 +9,8 @@ "defence": 30 } } - } + }, + "groups": ["adamant_metal", "equipment"] } }, @@ -31,7 +32,8 @@ "magic": -4, "ranged": 31 } - } + }, + "groups": ["legs"] }, "rs:adamant_plateskirt": { @@ -52,6 +54,7 @@ "magic": -4, "ranged": 31 } - } + }, + "groups": ["legs"] } } diff --git a/data/config/items/equipment/standard-metals/black-armour.json b/data/config/items/equipment/standard-metals/black-armour.json index f4488aedc..1c8a919a3 100644 --- a/data/config/items/equipment/standard-metals/black-armour.json +++ b/data/config/items/equipment/standard-metals/black-armour.json @@ -9,7 +9,8 @@ "defence": 10 } } - } + }, + "groups": ["black_metal", "equipment"] } }, @@ -31,7 +32,8 @@ "magic": -4, "ranged": 20 } - } + }, + "groups": ["legs"] }, "rs:black_plateskirt": { @@ -52,6 +54,7 @@ "magic": -4, "ranged": 20 } - } + }, + "groups": ["legs"] } } diff --git a/data/config/items/equipment/standard-metals/bronze-armour.json b/data/config/items/equipment/standard-metals/bronze-armour.json index 71d91a115..1d2dc8d0c 100644 --- a/data/config/items/equipment/standard-metals/bronze-armour.json +++ b/data/config/items/equipment/standard-metals/bronze-armour.json @@ -1,5 +1,20 @@ { + "presets": { + "rs:bronze_armour_base": { + "tradable": true, + "equippable": true, + "equipment_data": { + "requirements": { + "skills": { + "defence": 1 + } + } + }, + "groups": ["bronze_metal", "equipment"] + } + }, "rs:bronze_platelegs": { + "extends": "rs:bronze_armour_base", "game_id": 1075, "examine": "These look pretty heavy.", "weight": 9.071, @@ -18,11 +33,13 @@ "magic": -4, "ranged": 7 } - } + }, + "groups": ["legs"] }, "rs:bronze_plateskirt": { "game_id": 1087, + "extends": "rs:bronze_armour_base", "examine": "Designer leg protection.", "weight": 8.164, "tradable": true, @@ -40,6 +57,7 @@ "magic": -4, "ranged": 7 } - } + }, + "groups": ["legs"] } } diff --git a/data/config/items/equipment/standard-metals/bronze-weapons.json b/data/config/items/equipment/standard-metals/bronze-weapons.json index 690e3b76b..edbd8c96c 100644 --- a/data/config/items/equipment/standard-metals/bronze-weapons.json +++ b/data/config/items/equipment/standard-metals/bronze-weapons.json @@ -1,6 +1,21 @@ { + "presets": { + "rs:bronze_weapon_base": { + "tradable": true, + "equippable": true, + "equipment_data": { + "requirements": { + "skills": { + "defence": 1 + } + } + }, + "groups": ["bronze_metal", "equipment", "weapon"] + } + }, "rs:bronze_dagger": { "game_id": 1205, + "extends": "rs:bronze_weapon_base", "tradable": true, "weight": 0.453, "equippable": true, @@ -9,7 +24,7 @@ "equipment_type": "one_handed", "requirements": { "quests": { - "goblin_diplomacy": 20 + "tyn:goblin_diplomacy": 20 } }, "offensive_bonuses": { @@ -28,6 +43,7 @@ "weapon_info": { "style": "dagger" } - } + }, + "groups": ["main_hand", "dagger"] } } diff --git a/data/config/items/equipment/standard-metals/rune-armour.json b/data/config/items/equipment/standard-metals/rune-armour.json new file mode 100644 index 000000000..64af7772f --- /dev/null +++ b/data/config/items/equipment/standard-metals/rune-armour.json @@ -0,0 +1,265 @@ +{ + "presets": { + "rs:rune_armour_base": { + "tradable": true, + "equippable": true, + "equipment_data": { + "requirements": { + "skills": { + "defence": 40 + } + } + } + } + }, + + "rs:rune_gloves": { + "game_id": 7460, + "examine": "A pair of very nice gloves.", + "weight": 0.226, + "tradable": false, + "equipment_data": { + "equipment_slot": "hands", + "offensive_bonuses": { + "stab": 8, + "slash": 8, + "crush": 8, + "magic": 4, + "ranged": 8 + }, + "defensive_bonuses": { + "stab": 8, + "slash": 8, + "crush": 8, + "magic": 4, + "ranged": 8 + }, + "skill_bonuses": { + "strength": 8 + } + } + }, + + "rs:rune_defender": { + "extends": "rs:rune_armour_base", + "game_id": 8850, + "examine": "A defensive weapon.", + "weight": 0.453, + "equipment_data": { + "equipment_slot": "off_hand", + "requirements": { + "skills": { + "attack": 40 + } + }, + "offensive_bonuses": { + "stab": 20, + "slash": 19, + "crush": 18, + "magic": -3, + "ranged": -2 + }, + "defensive_bonuses": { + "stab": 20, + "slash": 19, + "crush": 18, + "magic": -3, + "ranged": -2 + }, + "skill_bonuses": { + "strength": 5 + } + } + }, + + "rs:rune_boots": { + "extends": "rs:rune_armour_base", + "game_id": 4131, + "examine": "These will protect my feet.", + "weight": 1.36, + "equipment_data": { + "equipment_slot": "feet", + "offensive_bonuses": { + "magic": -3, + "ranged": -1 + }, + "defensive_bonuses": { + "stab": 12, + "slash": 13, + "crush": 14 + }, + "skill_bonuses": { + "strength": 2 + } + } + }, + + "rs:rune_med_helm": { + "extends": "rs:rune_armour_base", + "game_id": 1147, + "examine": "A medium sized helmet.", + "weight": 1.814, + "equipment_data": { + "equipment_slot": "head", + "offensive_bonuses": { + "magic": -3 + }, + "defensive_bonuses": { + "stab": 22, + "slash": 23, + "crush": 21, + "magic": -1, + "ranged": 22 + } + } + }, + + "rs:rune_full_helm": { + "extends": "rs:rune_armour_base", + "game_id": 1163, + "examine": "A full face helmet.", + "weight": 2.721, + "equipment_data": { + "equipment_slot": "head", + "offensive_bonuses": { + "magic": -6, + "ranged": -3 + }, + "defensive_bonuses": { + "stab": 30, + "slash": 32, + "crush": 27, + "magic": -1, + "ranged": 30 + } + } + }, + + "rs:rune_sq_shield": { + "extends": "rs:rune_armour_base", + "game_id": 1185, + "examine": "A medium square shield.", + "weight": 3.628, + "equipment_data": { + "equipment_slot": "off_hand", + "offensive_bonuses": { + "magic": -6 + }, + "defensive_bonuses": { + "stab": 38, + "slash": 40, + "crush": 36, + "ranged": 38 + } + } + }, + + "rs:rune_kiteshield": { + "extends": "rs:rune_armour_base", + "game_id": 1201, + "examine": "A large metal shield.", + "weight": 5.443, + "equipment_data": { + "equipment_slot": "off_hand", + "offensive_bonuses": { + "magic": -8, + "ranged": -3 + }, + "defensive_bonuses": { + "stab": 44, + "slash": 48, + "crush": 46, + "magic": -1, + "ranged": 46 + } + } + }, + + "rs:rune_platelegs": { + "extends": "rs:rune_armour_base", + "game_id": 1079, + "examine": "These look pretty heavy.", + "weight": 9.071, + "equipment_data": { + "equipment_slot": "legs", + "offensive_bonuses": { + "magic": -21, + "ranged": -11 + }, + "defensive_bonuses": { + "stab": 51, + "slash": 49, + "crush": 47, + "magic": -4, + "ranged": 49 + } + } + }, + + "rs:rune_plateskirt": { + "extends": "rs:rune_armour_base", + "game_id": 1093, + "examine": "Designer leg protection.", + "weight": 8.164, + "equipment_data": { + "equipment_slot": "legs", + "offensive_bonuses": { + "magic": -21, + "ranged": -11 + }, + "defensive_bonuses": { + "stab": 51, + "slash": 49, + "crush": 47, + "magic": -4, + "ranged": 49 + } + } + }, + + "rs:rune_chainbody": { + "extends": "rs:rune_armour_base", + "game_id": 1113, + "examine": "A series of connected metal rings.", + "weight": 6.803, + "equipment_data": { + "equipment_slot": "torso", + "offensive_bonuses": { + "magic": -15 + }, + "defensive_bonuses": { + "stab": 63, + "slash": 72, + "crush": 78, + "magic": -3, + "ranged": 65 + } + } + }, + + "rs:rune_platebody": { + "extends": "rs:rune_armour_base", + "game_id": 1127, + "examine": "Provides excellent protection.", + "weight": 9.979, + "equipment_data": { + "equipment_slot": "torso", + "offensive_bonuses": { + "magic": -30, + "ranged": -15 + }, + "defensive_bonuses": { + "stab": 82, + "slash": 80, + "crush": 72, + "magic": -6, + "ranged": 80 + }, + "requirements": { + "quests" : { + "rs:dragon_slayer": "complete" + } + } + } + } +} diff --git a/data/config/items/equipment/standard-metals/rune-god-armour.json b/data/config/items/equipment/standard-metals/rune-god-armour.json new file mode 100644 index 000000000..ac0d7e051 --- /dev/null +++ b/data/config/items/equipment/standard-metals/rune-god-armour.json @@ -0,0 +1,348 @@ +{ + "presets": { + "rs:rune_god_armour_base": { + "tradable": true, + "equippable": true, + "equipment_data": { + "requirements": { + "skills": { + "defence": 40 + } + }, + "skill_bonuses": { + "prayer": 1 + } + } + } + }, + + "rs:guthix_full_helm": { + "extends": "rs:rune_god_armour_base", + "game_id": 2673, + "examine": "A rune full face helmet in the colours of Guthix.", + "weight": 2.721, + "equipment_data": { + "equipment_slot": "head", + "offensive_bonuses": { + "magic": -6, + "ranged": -3 + }, + "defensive_bonuses": { + "stab": 30, + "slash": 32, + "crush": 27, + "magic": -1, + "ranged": 30 + } + } + }, + + "rs:guthix_kiteshield": { + "extends": "rs:rune_god_armour_base", + "game_id": 2675, + "examine": "Rune kiteshield in the colours of Guthix.", + "weight": 5.443, + "equipment_data": { + "equipment_slot": "off_hand", + "offensive_bonuses": { + "magic": -8, + "ranged": -3 + }, + "defensive_bonuses": { + "stab": 44, + "slash": 48, + "crush": 46, + "magic": -1, + "ranged": 46 + } + } + }, + + "rs:guthix_platelegs": { + "extends": "rs:rune_god_armour_base", + "game_id": 2671, + "examine": "Rune platelegs in the colours of Guthix.", + "weight": 9.071, + "equipment_data": { + "equipment_slot": "legs", + "offensive_bonuses": { + "magic": -21, + "ranged": -11 + }, + "defensive_bonuses": { + "stab": 51, + "slash": 49, + "crush": 47, + "magic": -4, + "ranged": 49 + } + } + }, + + "rs:guthix_plateskirt": { + "extends": "rs:rune_god_armour_base", + "game_id": 3480, + "examine": "Rune plateskirt in the colours of Guthix.", + "weight": 8.164, + "equipment_data": { + "equipment_slot": "legs", + "offensive_bonuses": { + "magic": -21, + "ranged": -11 + }, + "defensive_bonuses": { + "stab": 51, + "slash": 49, + "crush": 47, + "magic": -4, + "ranged": 49 + } + } + }, + + "rs:guthix_platebody": { + "extends": "rs:rune_god_armour_base", + "game_id": 2669, + "examine": "Rune platebody in the colours of Guthix.", + "weight": 9.979, + "equipment_data": { + "equipment_slot": "torso", + "offensive_bonuses": { + "magic": -30, + "ranged": -15 + }, + "defensive_bonuses": { + "stab": 82, + "slash": 80, + "crush": 72, + "magic": -6, + "ranged": 80 + }, + "requirements": { + "quests" : { + "rs:dragon_slayer": "complete" + } + } + } + }, + + "rs:zamorak_full_helm": { + "extends": "rs:rune_god_armour_base", + "game_id": 2657, + "examine": "A rune full face helmet in the colours of Zamorak.", + "weight": 2.721, + "equipment_data": { + "equipment_slot": "head", + "offensive_bonuses": { + "magic": -6, + "ranged": -3 + }, + "defensive_bonuses": { + "stab": 30, + "slash": 32, + "crush": 27, + "magic": -1, + "ranged": 30 + } + } + }, + + "rs:zamorak_kiteshield": { + "extends": "rs:rune_god_armour_base", + "game_id": 2659, + "examine": "Rune kiteshield in the colours of Zamorak.", + "weight": 5.443, + "equipment_data": { + "equipment_slot": "off_hand", + "offensive_bonuses": { + "magic": -8, + "ranged": -3 + }, + "defensive_bonuses": { + "stab": 44, + "slash": 48, + "crush": 46, + "magic": -1, + "ranged": 46 + } + } + }, + + "rs:zamorak_platelegs": { + "extends": "rs:rune_god_armour_base", + "game_id": 2655, + "examine": "Rune platelegs in the colours of Zamorak.", + "weight": 9.071, + "equipment_data": { + "equipment_slot": "legs", + "offensive_bonuses": { + "magic": -21, + "ranged": -11 + }, + "defensive_bonuses": { + "stab": 51, + "slash": 49, + "crush": 47, + "magic": -4, + "ranged": 49 + } + } + }, + + "rs:zamorak_plateskirt": { + "extends": "rs:rune_god_armour_base", + "game_id": 3478, + "examine": "Rune plateskirt in the colours of Zamorak.", + "weight": 8.164, + "equipment_data": { + "equipment_slot": "legs", + "offensive_bonuses": { + "magic": -21, + "ranged": -11 + }, + "defensive_bonuses": { + "stab": 51, + "slash": 49, + "crush": 47, + "magic": -4, + "ranged": 49 + } + } + }, + + "rs:zamorak_platebody": { + "extends": "rs:rune_god_armour_base", + "game_id": 2653, + "examine": "Rune platebody in the colours of Zamorak.", + "weight": 9.979, + "equipment_data": { + "equipment_slot": "torso", + "offensive_bonuses": { + "magic": -30, + "ranged": -15 + }, + "defensive_bonuses": { + "stab": 82, + "slash": 80, + "crush": 72, + "magic": -6, + "ranged": 80 + }, + "requirements": { + "quests" : { + "rs:dragon_slayer": "complete" + } + } + } + }, + + "rs:saradomin_full_helm": { + "extends": "rs:rune_god_armour_base", + "game_id": 2665, + "examine": "A rune full face helmet in the colours of Saradomin.", + "weight": 2.721, + "equipment_data": { + "equipment_slot": "head", + "offensive_bonuses": { + "magic": -6, + "ranged": -3 + }, + "defensive_bonuses": { + "stab": 30, + "slash": 32, + "crush": 27, + "magic": -1, + "ranged": 30 + } + } + }, + + "rs:saradomin_kiteshield": { + "extends": "rs:rune_god_armour_base", + "game_id": 2667, + "examine": "Rune kiteshield in the colours of Saradomin.", + "weight": 5.443, + "equipment_data": { + "equipment_slot": "off_hand", + "offensive_bonuses": { + "magic": -8, + "ranged": -3 + }, + "defensive_bonuses": { + "stab": 44, + "slash": 48, + "crush": 46, + "magic": -1, + "ranged": 46 + } + } + }, + + "rs:saradomin_platelegs": { + "extends": "rs:rune_god_armour_base", + "game_id": 2663, + "examine": "Rune platelegs in the colours of Saradomin.", + "weight": 9.071, + "equipment_data": { + "equipment_slot": "legs", + "offensive_bonuses": { + "magic": -21, + "ranged": -11 + }, + "defensive_bonuses": { + "stab": 51, + "slash": 49, + "crush": 47, + "magic": -4, + "ranged": 49 + } + } + }, + + "rs:saradomin_plateskirt": { + "extends": "rs:rune_god_armour_base", + "game_id": 3479, + "examine": "Rune plateskirt in the colours of Saradomin.", + "weight": 8.164, + "equipment_data": { + "equipment_slot": "legs", + "offensive_bonuses": { + "magic": -21, + "ranged": -11 + }, + "defensive_bonuses": { + "stab": 51, + "slash": 49, + "crush": 47, + "magic": -4, + "ranged": 49 + } + } + }, + + "rs:saradomin_platebody": { + "extends": "rs:rune_god_armour_base", + "game_id": 2661, + "examine": "Rune platebody in the colours of Saradomin.", + "weight": 9.979, + "equipment_data": { + "equipment_slot": "torso", + "offensive_bonuses": { + "magic": -30, + "ranged": -15 + }, + "defensive_bonuses": { + "stab": 82, + "slash": 80, + "crush": 72, + "magic": -6, + "ranged": 80 + }, + "requirements": { + "quests" : { + "rs:dragon_slayer": "complete" + } + } + } + } +} diff --git a/data/config/widgets.json5 b/data/config/widgets.json5 index 6f4691631..fc651a6e0 100644 --- a/data/config/widgets.json5 +++ b/data/config/widgets.json5 @@ -14,6 +14,25 @@ slot8: { modelId: 12, titleId: 48 } } }, + trading: { + firstStage: { + widgetId: 335, + titleId: 93, + source: { + containerId: 91 + }, + target: { + containerId: 92 + } + }, + finalStage: { + widgetId: 334, + }, + tabarea: { + widgetId: 336, + containerId: 0 + } + }, anvil: { widgetId: 312, }, diff --git a/docker-compose.yml b/docker-compose.yml index befb4ef9b..764c9919e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,16 +1,17 @@ version: "3.8" services: - rune-js-server: - image: node:14 - container_name: server + runejs_game_server: + build: + context: . + dockerfile: Dockerfile + volumes: + - ./data:/usr/src/app/data + - ./cache:/usr/src/app/cache + - ./config:/usr/src/app/config ports: - "43594:43594" - volumes: - - .:/usr/src/service - working_dir: /usr/src/service - command: npm run start networks: default: - name: rune_js_network + name: runejs_network diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 000000000..50d8c28f5 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,194 @@ +/* + * For a detailed explanation regarding each configuration property and type check, visit: + * https://jestjs.io/docs/configuration + */ + +export default { + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "C:\\Users\\james\\AppData\\Local\\Temp\\jest", + + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: undefined, + + // The directory where Jest should output its coverage files + coverageDirectory: "coverage", + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "\\\\node_modules\\\\" + // ], + + // Indicates which provider should be used to instrument code for coverage + // coverageProvider: "babel", + + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // The default configuration for fake timers + // fakeTimers: { + // "enableGlobally": false + // }, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], + + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "mjs", + // "cjs", + // "jsx", + // "ts", + // "tsx", + // "json", + // "node" + // ], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + // moduleNameMapper: {}, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + // preset: undefined, + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state before every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: undefined, + + // Automatically restore mock state and implementation before every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + // setupFilesAfterEnv: [], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + // testEnvironment: "jest-environment-node", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + testMatch: [ + "**/*.test.ts" + ], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "\\\\node_modules\\\\" + // ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jest-circus/runner", + + // A map from regular expressions to paths to transformers + // transform: undefined, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "\\\\node_modules\\\\", + // "\\.pnp\\.[^\\\\]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: undefined, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, +}; diff --git a/package-lock.json b/package-lock.json index 06bd12041..202d24c02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,78 @@ { "name": "@runejs/server", - "version": "1.0.0-alpha.1", - "lockfileVersion": 1, + "version": "1.0.0-alpha.2", + "lockfileVersion": 2, "requires": true, - "dependencies": { - "@babel/cli": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.14.5.tgz", - "integrity": "sha512-poegjhRvXHWO0EAsnYajwYZuqcz7gyfxwfaecUESxDujrqOivf3zrjFbub8IJkrqEaz3fvJWh001EzxBub54fg==", + "packages": { + "": { + "name": "@runejs/server", + "version": "1.0.0-alpha.2", + "license": "GPL-3.0", + "dependencies": { + "@runejs/common": "^2.0.1", + "@runejs/login-server": "^2.0.0", + "@runejs/store": "^1.0.0-beta.1", + "@runejs/update-server": "^1.3.0", + "bigi": "^1.4.2", + "js-yaml": "^3.14.1", + "json5": "^2.2.2", + "lodash": "^4.17.21", + "quadtree-lib": "^1.0.9", + "rxjs": "^7.5.4", + "source-map-support": "^0.5.19", + "tslib": "^2.3.1", + "uuid": "^3.4.0", + "yargs": "^15.4.1" + }, + "devDependencies": { + "@babel/cli": "^7.17.6", + "@babel/core": "^7.17.5", + "@babel/node": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/preset-env": "^7.16.11", + "@babel/preset-typescript": "^7.16.7", + "@runejs/eslint-config": "^1.0.0", + "@types/jest": "^28.1.4", + "@types/js-yaml": "^3.12.7", + "@types/json5": "0.0.30", + "@types/lodash": "^4.14.179", + "@types/node": "^16.11.26", + "@types/uuid": "^3.4.10", + "@types/yargs": "^15.0.14", + "@typescript-eslint/eslint-plugin": "^4.33.0", + "@typescript-eslint/parser": "^4.33.0", + "babel-plugin-module-resolver": "^4.1.0", + "chokidar": "^3.5.3", + "concurrently": "^5.3.0", + "eslint": "^7.32.0", + "jest": "^28.1.2", + "mkdirp": "^1.0.4", + "nodemon": "^2.0.20", + "rimraf": "^3.0.2", + "ts-node": "^10.5.0", + "tsconfig-paths": "^3.12.0", + "typescript": "^4.5.5" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", "dev": true, - "requires": { - "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.2", - "chokidar": "^3.4.0", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/cli": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.17.6.tgz", + "integrity": "sha512-l4w608nsDNlxZhiJ5tE3DbNmr61fIKMZ6fTBo171VEFuFMIYuJ3mHRhTLEkKKyvx2Mizkkv/0a8OJOnZqkKYNA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.4", "commander": "^4.0.1", "convert-source-map": "^1.1.0", "fs-readdir-recursive": "^1.1.0", @@ -20,4351 +81,15381 @@ "slash": "^2.0.0", "source-map": "^0.5.0" }, + "bin": { + "babel": "bin/babel.js", + "babel-external-helpers": "bin/babel-external-helpers.js" + }, + "engines": { + "node": ">=6.9.0" + }, + "optionalDependencies": { + "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", + "chokidar": "^3.4.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/cli/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@babel/cli/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, "dependencies": { - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" } }, - "@babel/code-frame": { + "node_modules/@babel/cli/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/code-frame": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "dev": true, - "requires": { + "dependencies": { "@babel/highlight": "^7.10.4" } }, - "@babel/compat-data": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.1.tgz", - "integrity": "sha512-CHvCj7So7iCkGKPRFUfryXIkU2gSBw7VSZFYLsqVhrS47269VK2Hfi9S/YcublPMW8k1u2bQBlbDruoQEm4fgw==", + "node_modules/@babel/compat-data": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", + "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", "dev": true, - "requires": { - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "semver": "^5.5.0" + "engines": { + "node": ">=6.9.0" } }, - "@babel/core": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz", - "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.1", - "@babel/generator": "^7.10.2", - "@babel/helper-module-transforms": "^7.10.1", - "@babel/helpers": "^7.10.1", - "@babel/parser": "^7.10.2", - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.2", + "node_modules/@babel/core": { + "version": "7.17.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", + "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helpers": "^7.17.2", + "@babel/parser": "^7.17.3", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", + "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" + "semver": "^6.3.0" }, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", - "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.1" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", - "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", - "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.1", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "@babel/generator": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz", - "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==", + "node_modules/@babel/core/node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dev": true, - "requires": { - "@babel/types": "^7.10.2", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - }, "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-annotate-as-pure": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz", - "integrity": "sha512-ewp3rvJEwLaHgyWGe4wQssC2vjks3E80WiUe2BpMb0KhreTjMROCbxXcEovTrbeGVdQct5VjQfrv9EgC+xMzCw==", + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "requires": { - "@babel/types": "^7.10.1" + "bin": { + "semver": "bin/semver.js" } }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.1.tgz", - "integrity": "sha512-cQpVq48EkYxUU0xozpGCLla3wlkdRRqLWu1ksFMXA9CM5KQmyyRpSEsYXbao7JUkOw/tAaYKCaYyZq6HOFYtyw==", + "node_modules/@babel/generator": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", + "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.10.1", - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-compilation-targets": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz", - "integrity": "sha512-hYgOhF4To2UTB4LTaZepN/4Pl9LD4gfbJx8A34mqoluT8TLbof1mhUlYuNWTEebONa8+UlCC4X0TEXu7AOUyGA==", + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true, - "requires": { - "@babel/compat-data": "^7.10.1", - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "levenary": "^1.1.1", - "semver": "^5.5.0" + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-create-class-features-plugin": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.2.tgz", - "integrity": "sha512-5C/QhkGFh1vqcziq1vAL6SI9ymzUp8BCYjFpvYVhWP4DlATIb3u5q3iUd35mvlyGs8fO7hckkW7i0tmH+5+bvQ==", + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.1", - "@babel/helper-member-expression-to-functions": "^7.10.1", - "@babel/helper-optimise-call-expression": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/helper-replace-supers": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.1.tgz", - "integrity": "sha512-Rx4rHS0pVuJn5pJOqaqcZR4XSgeF9G/pO/79t+4r7380tXFJdzImFnxMU19f83wjSrmKHq6myrM10pFHTGzkUA==", + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.1", - "@babel/helper-regex": "^7.10.1", - "regexpu-core": "^4.7.0" + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-define-map": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.1.tgz", - "integrity": "sha512-+5odWpX+OnvkD0Zmq7panrMuAGQBu6aPUgvMzuMGo4R+jUOvealEj2hiqI6WhxgKrTpFoFj0+VdsuA8KDxHBDg==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", + "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.1", - "@babel/types": "^7.10.1", - "lodash": "^4.17.13" + "dependencies": { + "@babel/compat-data": "^7.16.4", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.17.5", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/helper-explode-assignable-expression": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.1.tgz", - "integrity": "sha512-vcUJ3cDjLjvkKzt6rHrl767FeE7pMEYfPanq5L16GRtrXIoznc0HykNW2aEYkcnP76P0isoqJ34dDMFZwzEpJg==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "requires": { - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "bin": { + "semver": "bin/semver.js" } }, - "@babel/helper-function-name": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz", - "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==", + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz", + "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==", "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/helper-get-function-arity": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz", - "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==", + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", + "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", "dev": true, - "requires": { - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/helper-hoist-variables": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.1.tgz", - "integrity": "sha512-vLm5srkU8rI6X3+aQ1rQJyfjvCBLXP8cAGeuw04zeAM2ItKb1e7pmVmLyHb4sDaAYnLL13RHOZPLEtcGZ5xvjg==", + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", "dev": true, - "requires": { - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" } }, - "@babel/helper-member-expression-to-functions": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz", - "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==", + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "requires": { - "@babel/types": "^7.10.1" + "bin": { + "semver": "bin/semver.js" } }, - "@babel/helper-module-imports": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz", - "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==", + "node_modules/@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", "dev": true, - "requires": { - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-module-transforms": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz", - "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==", + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.1", - "@babel/helper-replace-supers": "^7.10.1", - "@babel/helper-simple-access": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1", - "lodash": "^4.17.13" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-optimise-call-expression": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz", - "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==", + "node_modules/@babel/helper-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", + "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", "dev": true, - "requires": { - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/helper-get-function-arity": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-plugin-utils": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.1.tgz", - "integrity": "sha512-fvoGeXt0bJc7VMWZGCAEBEMo/HAjW2mP8apF5eXK0wSqwLAVHAISCWRoLMBMUs2kqeaG77jltVqu4Hn8Egl3nA==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.1.tgz", - "integrity": "sha512-7isHr19RsIJWWLLFn21ubFt223PjQyg1HY7CZEMRr820HttHPpVvrsIN3bUOo44DEfFV4kBXO7Abbn9KTUZV7g==", + "node_modules/@babel/helper-get-function-arity": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", + "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", "dev": true, - "requires": { - "lodash": "^4.17.13" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-remap-async-to-generator": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.1.tgz", - "integrity": "sha512-RfX1P8HqsfgmJ6CwaXGKMAqbYdlleqglvVtht0HGPMSsy2V6MqLlOJVF/0Qyb/m2ZCi2z3q3+s6Pv7R/dQuZ6A==", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.1", - "@babel/helper-wrap-function": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-replace-supers": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz", - "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz", + "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==", "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.1", - "@babel/helper-optimise-call-expression": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-simple-access": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz", - "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==", + "node_modules/@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", "dev": true, - "requires": { - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-split-export-declaration": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz", - "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz", + "integrity": "sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==", "dev": true, - "requires": { - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.1.tgz", - "integrity": "sha512-C0MzRGteVDn+H32/ZgbAv5r56f2o1fZSA/rj/TYo8JEJNHg+9BdSmKBUND0shxWRztWhjlT2cvHYuynpPsVJwQ==", + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helpers": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz", - "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", "dev": true, - "requires": { - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "engines": { + "node": ">=6.9.0" } }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/node": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.12.1.tgz", - "integrity": "sha512-S4tWOqo3V3ZuJjJNuheSMFIlDaQd6kbvqnQll+tdJTirksTdFHrauQf3d/xW4rgAM+mHJpxTZMHVeIXjCiDViw==", + "node_modules/@babel/helper-replace-supers": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", + "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", "dev": true, - "requires": { - "@babel/register": "^7.12.1", - "commander": "^4.0.1", - "core-js": "^3.2.1", - "lodash": "^4.17.19", - "node-environment-flags": "^1.0.5", - "regenerator-runtime": "^0.13.4", - "resolve": "^1.13.1", - "v8flags": "^3.1.1" - }, "dependencies": { - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - } + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/parser": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", - "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.1.tgz", - "integrity": "sha512-vzZE12ZTdB336POZjmpblWfNNRpMSua45EYnRigE2XsZxcXcIyly2ixnTJasJE4Zq3U7t2d8rRF7XRUuzHxbOw==", + "node_modules/@babel/helper-simple-access": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", + "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/helper-remap-async-to-generator": "^7.10.1", - "@babel/plugin-syntax-async-generators": "^7.8.0" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/plugin-proposal-class-properties": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.1.tgz", - "integrity": "sha512-sqdGWgoXlnOdgMXU+9MbhzwFRgxVLeiGBqTrnuS7LC2IBU31wSsESbTUreT2O418obpfPdGUR2GbEufZF1bpqw==", + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.1.tgz", - "integrity": "sha512-Cpc2yUVHTEGPlmiQzXj026kqwjEQAD9I4ZC16uzdbgWgitg/UHKHLffKNCQZ5+y8jpIZPJcKcwsr2HwPh+w3XA==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/plugin-proposal-json-strings": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.1.tgz", - "integrity": "sha512-m8r5BmV+ZLpWPtMY2mOKN7wre6HIO4gfIiV+eOmsnZABNenrt/kzYBwrh+KOfgumSWpnlGs5F70J8afYMSJMBg==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-syntax-json-strings": "^7.8.0" + "engines": { + "node": ">=6.9.0" } }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.1.tgz", - "integrity": "sha512-56cI/uHYgL2C8HVuHOuvVowihhX0sxb3nnfVRzUeVHTWmRHTZrKuAh/OBIMggGU/S1g/1D2CRCXqP+3u7vX7iA==", + "node_modules/@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + "engines": { + "node": ">=6.9.0" } }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.1.tgz", - "integrity": "sha512-jjfym4N9HtCiNfyyLAVD8WqPYeHUrw4ihxuAynWj6zzp2gf9Ey2f7ImhFm6ikB3CLf5Z/zmcJDri6B4+9j9RsA==", + "node_modules/@babel/helper-wrap-function": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-syntax-numeric-separator": "^7.10.1" + "dependencies": { + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.1.tgz", - "integrity": "sha512-Z+Qri55KiQkHh7Fc4BW6o+QBuTagbOp9txE+4U1i79u9oWlf2npkiDx+Rf3iK3lbcHBuNy9UOkwuR5wOMH3LIQ==", + "node_modules/@babel/helpers": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", + "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.10.1" + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.0", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.1.tgz", - "integrity": "sha512-VqExgeE62YBqI3ogkGoOJp1R6u12DFZjqwJhqtKc2o5m1YTUuUWnos7bZQFBhwkxIFpWYJ7uB75U7VAPPiKETA==", + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.1.tgz", - "integrity": "sha512-dqQj475q8+/avvok72CF3AOSV/SGEcH29zT5hhohqqvvZ2+boQoOr7iGldBG5YXTO2qgCgc2B3WvVLUdbeMlGA==", + "node_modules/@babel/node": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.16.8.tgz", + "integrity": "sha512-V2dopEtPUL4LD+e8UtMIZB6BbsmMsS/7E1ZAvWNINzBfi7Cf3X9MLCpzHVZT4HeeF1lQl72IRtqqVt2RUImwyA==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.1.tgz", - "integrity": "sha512-RZecFFJjDiQ2z6maFprLgrdnm0OzoC23Mx89xf1CcEsxmHuzuXOdniEuI+S3v7vjQG4F5sa6YtUp+19sZuSxHg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/register": "^7.16.8", + "commander": "^4.0.1", + "core-js": "^3.20.2", + "node-environment-flags": "^1.0.5", + "regenerator-runtime": "^0.13.4", + "v8flags": "^3.1.1" + }, + "bin": { + "babel-node": "bin/babel-node.js" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.1.tgz", - "integrity": "sha512-JjfngYRvwmPwmnbRZyNiPFI8zxCZb8euzbCG/LxyKdeTb59tVciKo9GK9bi6JYKInk1H11Dq9j/zRqIH4KigfQ==", + "node_modules/@babel/node/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "engines": { + "node": ">= 6" } }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "node_modules/@babel/parser": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", + "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "@babel/plugin-syntax-class-properties": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz", - "integrity": "sha512-Gf2Yx/iRs1JREDtVZ56OrjjgFHCaldpTnuy9BHla10qyVT3YkIIGEtoDWhyop0ksu1GvNjHIoYRBqm3zoR1jyQ==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", + "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", + "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", + "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", + "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.1.tgz", - "integrity": "sha512-uTd0OsHrpe3tH5gRPTxG8Voh99/WCU78vIm5NMRYPAqC8lR4vajt6KkCAknCHrx24vkPdd/05yfdGSB4EIY2mg==", + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", + "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.6", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" } }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", + "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", + "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.1.tgz", - "integrity": "sha512-hgA5RYkmZm8FTFT3yu2N9Bx7yVVOKYT6yEdXXo6j2JTm0wNxgqaGeQVaSHRjhfnQbX91DtjFB6McRFSlcJH3xQ==", + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", + "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-typescript": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.1.tgz", - "integrity": "sha512-X/d8glkrAtra7CaQGMiGs/OGa6XgUzqPcBXCIGFCpCqnfGlT0Wfbzo/B89xHhnInTaItPK8LALblVXcUOEh95Q==", + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", + "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.1.tgz", - "integrity": "sha512-6AZHgFJKP3DJX0eCNJj01RpytUa3SOGawIxweHkNX2L6PYikOZmoh5B0d7hIHaIgveMjX990IAa/xK7jRTN8OA==", + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.1.tgz", - "integrity": "sha512-XCgYjJ8TY2slj6SReBUyamJn3k2JLUIiiR5b6t1mNCMSvv7yx+jJpaewakikp0uWFQSF7ChPPoe3dHmXLpISkg==", + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", + "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/helper-remap-async-to-generator": "^7.10.1" + "dependencies": { + "@babel/compat-data": "^7.17.0", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.1.tgz", - "integrity": "sha512-B7K15Xp8lv0sOJrdVAoukKlxP9N59HS48V1J3U/JGj+Ad+MHq+am6xJVs85AgXrQn4LV8vaYFOB+pr/yIuzW8Q==", + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-block-scoping": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.1.tgz", - "integrity": "sha512-8bpWG6TtF5akdhIm/uWTyjHqENpy13Fx8chg7pFH875aNLwX8JxIxqm08gmAT+Whe6AOmaTeLPe7dpLbXt+xUw==", + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", + "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "lodash": "^4.17.13" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-classes": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.1.tgz", - "integrity": "sha512-P9V0YIh+ln/B3RStPoXpEQ/CoAxQIhRSUn7aXqQ+FZJ2u8+oCtjIXR3+X0vsSD8zv+mb56K7wZW1XiDTDGiDRQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.1", - "@babel/helper-define-map": "^7.10.1", - "@babel/helper-function-name": "^7.10.1", - "@babel/helper-optimise-call-expression": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/helper-replace-supers": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1", - "globals": "^11.1.0" + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", + "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.10", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-computed-properties": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.1.tgz", - "integrity": "sha512-mqSrGjp3IefMsXIenBfGcPXxJxweQe2hEIwMQvjtiDQ9b1IBvDUjkAtV/HMXX47/vXf14qDNedXsIiNd1FmkaQ==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", + "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-destructuring": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.1.tgz", - "integrity": "sha512-V/nUc4yGWG71OhaTH705pU8ZSdM6c1KmmLP8ys59oOYbT7RpMYAR3MsVOt6OHL0WzG7BlTU076va9fjJyYzJMA==", + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", + "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.1.tgz", - "integrity": "sha512-19VIMsD1dp02RvduFUmfzj8uknaO3uiHHF0s3E1OHnVsNj8oge8EQ5RzHRbJjGSetRnkEuBYO7TG1M5kKjGLOA==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.1.tgz", - "integrity": "sha512-wIEpkX4QvX8Mo9W6XF3EdGttrIPZWozHfEaDTU0WJD/TDnXMvdDh30mzUl/9qWhnf7naicYartcEfUghTCSNpA==", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.1.tgz", - "integrity": "sha512-lr/przdAbpEA2BUzRvjXdEDLrArGRRPwbaF9rvayuHRvdQ7lUTTkZnhZrJ4LE2jvgMRFF4f0YuPQ20vhiPYxtA==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-for-of": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.1.tgz", - "integrity": "sha512-US8KCuxfQcn0LwSCMWMma8M2R5mAjJGsmoCBVwlMygvmDUMkTCykc84IqN1M7t+agSfOmLYTInLCHJM+RUoz+w==", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-function-name": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.1.tgz", - "integrity": "sha512-//bsKsKFBJfGd65qSNNh1exBy5Y9gD9ZN+DvrJ8f7HXr4avE5POW6zB7Rj6VnqHV33+0vXWUwJT0wSHubiAQkw==", + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-literals": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.1.tgz", - "integrity": "sha512-qi0+5qgevz1NHLZroObRm5A+8JJtibb7vdcPQF1KQE12+Y/xxl8coJ+TpPW9iRq+Mhw/NKLjm+5SHtAHCC7lAw==", + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.1.tgz", - "integrity": "sha512-UmaWhDokOFT2GcgU6MkHC11i0NQcL63iqeufXWfRy6pUOGYeCGEKhvfFO6Vz70UfYJYHwveg62GS83Rvpxn+NA==", + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-modules-amd": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.1.tgz", - "integrity": "sha512-31+hnWSFRI4/ACFr1qkboBbrTxoBIzj7qA69qlq8HY8p7+YCzkCT6/TvQ1a4B0z27VeWtAeJd6pr5G04dc1iHw==", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.1.tgz", - "integrity": "sha512-AQG4fc3KOah0vdITwt7Gi6hD9BtQP/8bhem7OjbaMoRNCH5Djx42O2vYMfau7QnAzQCa+RJnhJBmFFMGpQEzrg==", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/helper-simple-access": "^7.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.1.tgz", - "integrity": "sha512-ewNKcj1TQZDL3YnO85qh9zo1YF1CHgmSTlRQgHqe63oTrMI85cthKtZjAiZSsSNjPQ5NCaYo5QkbYqEw1ZBgZA==", + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.10.1", - "@babel/helper-module-transforms": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "babel-plugin-dynamic-import-node": "^2.3.3" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-modules-umd": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.1.tgz", - "integrity": "sha512-EIuiRNMd6GB6ulcYlETnYYfgv4AxqrswghmBRQbWLHZxN4s7mupxzglnHqk9ZiUpDI4eRWewedJJNj67PWOXKA==", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-named-capturing-groups-regex": { + "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", - "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-new-target": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.1.tgz", - "integrity": "sha512-MBlzPc1nJvbmO9rPr1fQwXOM2iGut+JC92ku6PbiJMMK7SnQc1rytgpopveE3Evn47gzvGYeCdgfCDbZo0ecUw==", + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-object-super": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.1.tgz", - "integrity": "sha512-WnnStUDN5GL+wGQrJylrnnVlFhFmeArINIR9gjhSeYyvroGhBrSAXYg/RHsnfzmsa+onJrTJrEClPzgNmmQ4Gw==", + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/helper-replace-supers": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-parameters": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.1.tgz", - "integrity": "sha512-tJ1T0n6g4dXMsL45YsSzzSDZCxiHXAQp/qHrucOq5gEHncTA3xDxnd5+sZcoQp+N1ZbieAaB8r/VUCG0gqseOg==", + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-property-literals": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.1.tgz", - "integrity": "sha512-Kr6+mgag8auNrgEpbfIWzdXYOvqDHZOF0+Bx2xh4H2EDNwcbRb9lY6nkZg8oSjsX+DH9Ebxm9hOqtKW+gRDeNA==", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-regenerator": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.1.tgz", - "integrity": "sha512-B3+Y2prScgJ2Bh/2l9LJxKbb8C8kRfsG4AdPT+n7ixBHIxJaIG8bi8tgjxUMege1+WqSJ+7gu1YeoMVO3gPWzw==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", + "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-reserved-words": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.1.tgz", - "integrity": "sha512-qN1OMoE2nuqSPmpTqEM7OvJ1FkMEV+BjVeZZm9V9mq/x1JLKQ4pcv8riZJMNN3u2AUGl0ouOMjRr2siecvHqUQ==", + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", + "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.1.tgz", - "integrity": "sha512-AR0E/lZMfLstScFwztApGeyTHJ5u3JUKMjneqRItWeEqDdHWZwAOKycvQNCasCK/3r5YXsuNG25funcJDu7Y2g==", + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", + "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-spread": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.1.tgz", - "integrity": "sha512-8wTPym6edIrClW8FI2IoaePB91ETOtg36dOkj3bYcNe7aDMN2FXEoUa+WrmPc4xa1u2PQK46fUX2aCb+zo9rfw==", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.1.tgz", - "integrity": "sha512-j17ojftKjrL7ufX8ajKvwRilwqTok4q+BjkknmQw9VNHnItTyMP5anPFzxFJdCQs7clLcWpCV3ma+6qZWLnGMA==", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", + "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/helper-regex": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-template-literals": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.1.tgz", - "integrity": "sha512-t7B/3MQf5M1T9hPCRG28DNGZUuxAuDqLYS03rJrIk2prj/UV7Z6FOneijhQhnv/Xa039vidXeVbvjK2SK5f7Gg==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", + "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.1.tgz", - "integrity": "sha512-qX8KZcmbvA23zDi+lk9s6hC1FM7jgLHYIjuLgULgc8QtYnmB3tAVIYkNoKRQ75qWBeyzcoMoK8ZQmogGtC/w0g==", + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", + "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-typescript": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.10.1.tgz", - "integrity": "sha512-v+QWKlmCnsaimLeqq9vyCsVRMViZG1k2SZTlcZvB+TqyH570Zsij8nvVUZzOASCRiQFUxkLrn9Wg/kH0zgy5OQ==", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz", + "integrity": "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==", "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-syntax-typescript": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.1.tgz", - "integrity": "sha512-zZ0Poh/yy1d4jeDWpx/mNwbKJVwUYJX73q+gyh4bwtG0/iUlzdEu0sLMda8yuDFS6LBQlT/ST1SJAR6zYwXWgw==", + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.1.tgz", - "integrity": "sha512-Y/2a2W299k0VIUdbqYm9X2qS6fE0CUBhhiPpimK6byy7OJ/kORLlIX+J6UrjgNu5awvs62k+6RSslxhcvVw2Tw==", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", + "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/preset-env": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.2.tgz", - "integrity": "sha512-MjqhX0RZaEgK/KueRzh+3yPSk30oqDKJ5HP5tqTSB1e2gzGS3PLy7K0BIpnp78+0anFuSwOeuCf1zZO7RzRvEA==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.10.1", - "@babel/helper-compilation-targets": "^7.10.2", - "@babel/helper-module-imports": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-proposal-async-generator-functions": "^7.10.1", - "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/plugin-proposal-dynamic-import": "^7.10.1", - "@babel/plugin-proposal-json-strings": "^7.10.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1", - "@babel/plugin-proposal-numeric-separator": "^7.10.1", - "@babel/plugin-proposal-object-rest-spread": "^7.10.1", - "@babel/plugin-proposal-optional-catch-binding": "^7.10.1", - "@babel/plugin-proposal-optional-chaining": "^7.10.1", - "@babel/plugin-proposal-private-methods": "^7.10.1", - "@babel/plugin-proposal-unicode-property-regex": "^7.10.1", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.10.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.1", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.10.1", - "@babel/plugin-transform-arrow-functions": "^7.10.1", - "@babel/plugin-transform-async-to-generator": "^7.10.1", - "@babel/plugin-transform-block-scoped-functions": "^7.10.1", - "@babel/plugin-transform-block-scoping": "^7.10.1", - "@babel/plugin-transform-classes": "^7.10.1", - "@babel/plugin-transform-computed-properties": "^7.10.1", - "@babel/plugin-transform-destructuring": "^7.10.1", - "@babel/plugin-transform-dotall-regex": "^7.10.1", - "@babel/plugin-transform-duplicate-keys": "^7.10.1", - "@babel/plugin-transform-exponentiation-operator": "^7.10.1", - "@babel/plugin-transform-for-of": "^7.10.1", - "@babel/plugin-transform-function-name": "^7.10.1", - "@babel/plugin-transform-literals": "^7.10.1", - "@babel/plugin-transform-member-expression-literals": "^7.10.1", - "@babel/plugin-transform-modules-amd": "^7.10.1", - "@babel/plugin-transform-modules-commonjs": "^7.10.1", - "@babel/plugin-transform-modules-systemjs": "^7.10.1", - "@babel/plugin-transform-modules-umd": "^7.10.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", - "@babel/plugin-transform-new-target": "^7.10.1", - "@babel/plugin-transform-object-super": "^7.10.1", - "@babel/plugin-transform-parameters": "^7.10.1", - "@babel/plugin-transform-property-literals": "^7.10.1", - "@babel/plugin-transform-regenerator": "^7.10.1", - "@babel/plugin-transform-reserved-words": "^7.10.1", - "@babel/plugin-transform-shorthand-properties": "^7.10.1", - "@babel/plugin-transform-spread": "^7.10.1", - "@babel/plugin-transform-sticky-regex": "^7.10.1", - "@babel/plugin-transform-template-literals": "^7.10.1", - "@babel/plugin-transform-typeof-symbol": "^7.10.1", - "@babel/plugin-transform-unicode-escapes": "^7.10.1", - "@babel/plugin-transform-unicode-regex": "^7.10.1", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.10.2", - "browserslist": "^4.12.0", - "core-js-compat": "^3.6.2", - "invariant": "^2.2.2", - "levenary": "^1.1.1", - "semver": "^5.5.0" + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/preset-modules": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz", - "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", + "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/preset-typescript": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.10.1.tgz", - "integrity": "sha512-m6GV3y1ShiqxnyQj10600ZVOFrSSAa8HQ3qIUk2r+gcGtHTIRw0dJnFLt1WNXpKjtVw7yw1DAPU/6ma2ZvgJuA==", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-transform-typescript": "^7.10.1" + "dependencies": { + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/register": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.12.1.tgz", - "integrity": "sha512-XWcmseMIncOjoydKZnWvWi0/5CUCD+ZYKhRwgYlWOrA8fGZ/FjuLRpqtIhLOVD/fvR1b9DQHtZPn68VvhpYf+Q==", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", + "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", "dev": true, - "requires": { - "find-cache-dir": "^2.0.0", - "lodash": "^4.17.19", - "make-dir": "^2.1.0", - "pirates": "^4.0.0", - "source-map-support": "^0.5.16" - }, "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - } + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/runtime": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.2.tgz", - "integrity": "sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg==", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/template": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz", - "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==", + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", + "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", "dev": true, - "requires": { - "@babel/code-frame": "^7.10.1", - "@babel/parser": "^7.10.1", - "@babel/types": "^7.10.1" + "dependencies": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz", + "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==", + "dev": true, "dependencies": { - "@babel/code-frame": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", - "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.1" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", - "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", - "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.1", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - } + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/traverse": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz", - "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz", + "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==", "dev": true, - "requires": { - "@babel/code-frame": "^7.10.1", - "@babel/generator": "^7.10.1", - "@babel/helper-function-name": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1", - "@babel/parser": "^7.10.1", - "@babel/types": "^7.10.1", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" + "dependencies": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", + "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", + "dev": true, "dependencies": { - "@babel/code-frame": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", - "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.1" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", - "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", - "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.1", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/types": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz", - "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", + "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.1", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", + "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", + "dev": true, "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", - "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", - "dev": true - } + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", + "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", + "dev": true, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "globals": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", - "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "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 - }, - "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 - } + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@hapi/bourne": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz", - "integrity": "sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg==" + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", + "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" + "dependencies": { + "regenerator-transform": "^0.14.2" }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", + "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", + "dev": true, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", - "dev": true + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "@mapbox/node-pre-gyp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", - "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", - "requires": { - "detect-libc": "^1.0.3", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.1", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "rimraf": "^3.0.2", - "semver": "^7.3.4", - "tar": "^6.1.0" + "node_modules/@babel/plugin-transform-spread": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", + "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "dev": true, "dependencies": { - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "requires": { - "lru-cache": "^6.0.0" - } - } + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@nicolo-ribaudo/chokidar-2": { - "version": "2.1.8-no-fsevents.2", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.2.tgz", - "integrity": "sha512-Fb8WxUFOBQVl+CX4MWet5o7eCc6Pj04rXIwVKZ6h1NnqTo45eOQW6aWyhG25NIODvWFwTDMwBsYxrQ3imxpetg==", + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", + "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^5.1.2", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "optional": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "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, - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "optional": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@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==", + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", + "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@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 + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", + "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-typescript": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "@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==", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@runejs/core": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@runejs/core/-/core-1.5.4.tgz", - "integrity": "sha512-bYuYIIYMdI7ksGbQUjN+P3OW/Q4aaOgfo1R4kl+NBmPL+59jinNhC+WHfWTsX5Jvz3jU4WV9IuYELS1L9Kfzkw==", - "requires": { - "js-yaml": "^3.14.1", - "pino": "^6.13.0", - "pino-pretty": "^4.8.0" + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", + "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", + "dev": true, "dependencies": { - "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==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - } + "@babel/compat-data": "^7.16.8", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-async-generator-functions": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-class-static-block": "^7.16.7", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.16.7", + "@babel/plugin-proposal-json-strings": "^7.16.7", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.16.7", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-private-methods": "^7.16.11", + "@babel/plugin-proposal-private-property-in-object": "^7.16.7", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.16.7", + "@babel/plugin-transform-async-to-generator": "^7.16.8", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.16.7", + "@babel/plugin-transform-classes": "^7.16.7", + "@babel/plugin-transform-computed-properties": "^7.16.7", + "@babel/plugin-transform-destructuring": "^7.16.7", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.16.7", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.16.7", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.16.7", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.16.7", + "@babel/plugin-transform-modules-commonjs": "^7.16.8", + "@babel/plugin-transform-modules-systemjs": "^7.16.7", + "@babel/plugin-transform-modules-umd": "^7.16.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", + "@babel/plugin-transform-new-target": "^7.16.7", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.16.7", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.16.7", + "@babel/plugin-transform-reserved-words": "^7.16.7", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.16.7", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.16.7", + "@babel/plugin-transform-typeof-symbol": "^7.16.7", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.16.8", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@runejs/eslint-config": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@runejs/eslint-config/-/eslint-config-1.0.0.tgz", - "integrity": "sha512-Z4yELzMWGQ75ihZgPMIEUKucc1X5GvIu8ZYDxjKnjcCkTT3VvMRZ4mFvXxmrXy5kip2X/PR3Sklw6uIR9UCkBg==", - "dev": true + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } }, - "@runejs/filestore": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@runejs/filestore/-/filestore-0.15.2.tgz", - "integrity": "sha512-Di6iFbDR3DNDAQJ9yEyGOb6xP1QIrvGZyoe5aaZBJbuE8Y+INSvWv0hB4PJYcP6scbWKd6CSsUHBpzvUtRstVw==", - "requires": { - "@runejs/core": "^1.5.4", - "canvas": "^2.8.0", - "node-properties-parser": "0.0.2", - "pngjs": "^6.0.0", - "seek-bzip": "^1.0.5", - "tslib": "^2.1.0" + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@runejs/login-server": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@runejs/login-server/-/login-server-1.2.2.tgz", - "integrity": "sha512-du2z7hTkv3x5CmqlKPOMaFO4eN0HnA6IKbDTsV8L77SSBWkO8lWBLGKVOIxpbAd29cZ0dwHjOEPizf6epmFxCg==", - "requires": { - "@runejs/core": "^1.5.4", - "bcrypt": "^5.0.1", - "bigi": "^1.4.2", - "source-map-support": "^0.5.19", - "tslib": "^2.2.0" + "node_modules/@babel/preset-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", + "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-typescript": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.0.tgz", + "integrity": "sha512-UNZsMAZ7uKoGHo1HlEXfteEOYssf64n/PNLHGqOKq/bgYcu/4LrQWAHJwSCb3BRZK8Hi5gkJdRcwrGTO2wtRCg==", + "dev": true, "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.5", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@runejs/update-server": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@runejs/update-server/-/update-server-1.2.2.tgz", - "integrity": "sha512-PQm210OYn24nyV5Eis8ef/KLPy6ZZuWluKvcLOBzXkr98ekxgn4+3p+tBCvhg8DkEBCvuKtDwTJCHhUWx/carQ==", - "requires": { - "@runejs/core": "^1.5.4", - "@runejs/filestore": "^0.15.2", - "crc-32": "^1.2.0", - "source-map-support": "^0.5.19", - "tslib": "^2.2.0" + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/runtime": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz", + "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==", + "dev": true, "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - } + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true + "node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dev": true, - "requires": { - "defer-to-connect": "^1.0.1" + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + "node_modules/@babel/traverse": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", + "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.3", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "@types/js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==", - "dev": true + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } }, - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true + "node_modules/@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "@types/json5": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.30.tgz", - "integrity": "sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@types/lodash": { - "version": "4.14.149", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", - "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", - "dev": true + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true, + "engines": { + "node": ">= 12" + } }, - "@types/node": { - "version": "14.14.37", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.37.tgz", - "integrity": "sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==", - "dev": true + "node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } }, - "@types/uuid": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.6.tgz", - "integrity": "sha512-cCdlC/1kGEZdEglzOieLDYBxHsvEOIg7kp/2FYyVR9Pxakq+Qf/inL3RKQ+PA8gOlI/NnL+fXmQH12nwcGzsHw==", + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, - "requires": { - "@types/node": "*" + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", "dev": true, - "requires": { - "@types/yargs-parser": "*" + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@types/yargs-parser": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", - "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", - "dev": true + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } }, - "@typescript-eslint/eslint-plugin": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.3.tgz", - "integrity": "sha512-tBgfA3K/3TsZY46ROGvoRxQr1wBkclbVqRQep97MjVHJzcRBURRY3sNFqLk0/Xr//BY5hM9H2p/kp+6qim85SA==", + "node_modules/@eslint/eslintrc/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, - "requires": { - "@typescript-eslint/experimental-utils": "4.29.3", - "@typescript-eslint/scope-manager": "4.29.3", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "engines": { + "node": ">=8" }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@typescript-eslint/experimental-utils": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.3.tgz", - "integrity": "sha512-ffIvbytTVWz+3keg+Sy94FG1QeOvmV9dP2YSdLFHw/ieLXWCa3U1TYu8IRCOpMv2/SPS8XqhM1+ou1YHsdzKrg==", + "node_modules/@hapi/bourne": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz", + "integrity": "sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg==" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", "dev": true, - "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.29.3", - "@typescript-eslint/types": "4.29.3", - "@typescript-eslint/typescript-estree": "4.29.3", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" } }, - "@typescript-eslint/parser": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.3.tgz", - "integrity": "sha512-jrHOV5g2u8ROghmspKoW7pN8T/qUzk0+DITun0MELptvngtMrwUJ1tv5zMI04CYVEUsSrN4jV7AKSv+I0y0EfQ==", + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "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, - "requires": { - "@typescript-eslint/scope-manager": "4.29.3", - "@typescript-eslint/types": "4.29.3", - "@typescript-eslint/typescript-estree": "4.29.3", - "debug": "^4.3.1" - }, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } + "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" } }, - "@typescript-eslint/scope-manager": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.3.tgz", - "integrity": "sha512-x+w8BLXO7iWPkG5mEy9bA1iFRnk36p/goVlYobVWHyDw69YmaH9q6eA+Fgl7kYHmFvWlebUTUfhtIg4zbbl8PA==", + "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, - "requires": { - "@typescript-eslint/types": "4.29.3", - "@typescript-eslint/visitor-keys": "4.29.3" + "engines": { + "node": ">=8" } }, - "@typescript-eslint/types": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.3.tgz", - "integrity": "sha512-s1eV1lKNgoIYLAl1JUba8NhULmf+jOmmeFO1G5MN/RBCyyzg4TIOfIOICVNC06lor+Xmy4FypIIhFiJXOknhIg==", - "dev": true + "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" + } }, - "@typescript-eslint/typescript-estree": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.3.tgz", - "integrity": "sha512-45oQJA0bxna4O5TMwz55/TpgjX1YrAPOI/rb6kPgmdnemRZx/dB0rsx+Ku8jpDvqTxcE1C/qEbVHbS3h0hflag==", + "node_modules/@jest/console": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.1.tgz", + "integrity": "sha512-0RiUocPVFEm3WRMOStIHbRWllG6iW6E3/gUPnf4lkrVFyXIIDeCe+vlKeYyFOMhB2EPE6FLFCNADSOOQMaqvyA==", "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.3", - "@typescript-eslint/visitor-keys": "4.29.3", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } + "@jest/types": "^28.1.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.1", + "jest-util": "^28.1.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "@typescript-eslint/visitor-keys": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.3.tgz", - "integrity": "sha512-MGGfJvXT4asUTeVs0Q2m+sY63UsfnA+C/FDgBKV3itLBmM9H0u+URcneePtkd0at1YELmZK6HSolCqM4Fzs6yA==", + "node_modules/@jest/console/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, - "requires": { - "@typescript-eslint/types": "4.29.3", - "eslint-visitor-keys": "^2.0.0" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true + "node_modules/@jest/console/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" + } }, - "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 + "node_modules/@jest/console/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" + } }, - "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==", - "requires": { - "debug": "4" - }, + "node_modules/@jest/console/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": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@jest/core": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.2.tgz", + "integrity": "sha512-Xo4E+Sb/nZODMGOPt2G3cMmCBqL4/W2Ijwr7/mrXlq4jdJwcFQ/9KrrJZT2adQRk2otVBXXOz1GRQ4Z5iOgvRQ==", "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "dependencies": { + "@jest/console": "^28.1.1", + "@jest/reporters": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^28.0.2", + "jest-config": "^28.1.2", + "jest-haste-map": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.1", + "jest-resolve-dependencies": "^28.1.2", + "jest-runner": "^28.1.2", + "jest-runtime": "^28.1.2", + "jest-snapshot": "^28.1.2", + "jest-util": "^28.1.1", + "jest-validate": "^28.1.1", + "jest-watcher": "^28.1.1", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.1", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "node_modules/@jest/core/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, - "requires": { - "string-width": "^3.0.0" - }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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==", + "node_modules/@jest/core/node_modules/ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", "dev": true }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" + "node_modules/@jest/core/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" } }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "node_modules/@jest/core/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "engines": { + "node": ">=8" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "node_modules/@jest/core/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" + } }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "node_modules/@jest/environment": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.2.tgz", + "integrity": "sha512-I0CR1RUMmOzd0tRpz10oUfaChBWs+/Hrvn5xYhMEF/ZqrDaaeHwS8yDBqEWCrEnkH2g+WE/6g90oBv3nKpcm8Q==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/node": "*", + "jest-mock": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "node_modules/@jest/expect": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.2.tgz", + "integrity": "sha512-HBzyZBeFBiOelNbBKN0pilWbbrGvwDUwAqMC46NVJmWm8AVkuE58NbG1s7DR4cxFt4U5cVLxofAoHxgvC5MyOw==", + "dev": true, + "dependencies": { + "expect": "^28.1.1", + "jest-snapshot": "^28.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" + "node_modules/@jest/expect-utils": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.1.tgz", + "integrity": "sha512-n/ghlvdhCdMI/hTcnn4qV57kQuV9OTsZzH1TTCVARANKhl6hXJqLKUkwX69ftMGpsbpt96SsDD8n8LD2d9+FRw==", + "dev": true, + "dependencies": { + "jest-get-type": "^28.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "args": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/args/-/args-5.0.1.tgz", - "integrity": "sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==", - "requires": { - "camelcase": "5.0.0", - "chalk": "2.4.2", - "leven": "2.1.0", - "mri": "1.1.4" - }, + "node_modules/@jest/fake-timers": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.2.tgz", + "integrity": "sha512-xSYEI7Y0D5FbZN2LsCUj/EKRR1zfQYmGuAUVh6xTqhx7V5JhjgMcK5Pa0iR6WIk0GXiHDe0Ke4A+yERKE9saqg==", + "dev": true, "dependencies": { - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==" - }, - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" - } + "@jest/types": "^28.1.1", + "@sinonjs/fake-timers": "^9.1.2", + "@types/node": "*", + "jest-message-util": "^28.1.1", + "jest-mock": "^28.1.1", + "jest-util": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "node_modules/@jest/globals": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.2.tgz", + "integrity": "sha512-cz0lkJVDOtDaYhvT3Fv2U1B6FtBnV+OpEyJCzTHM1fdoTsU4QNLAt/H4RkiwEUU+dL4g/MFsoTuHeT2pvbo4Hg==", "dev": true, - "optional": true + "dependencies": { + "@jest/environment": "^28.1.2", + "@jest/expect": "^28.1.2", + "@jest/types": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "node_modules/@jest/reporters": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.2.tgz", + "integrity": "sha512-/whGLhiwAqeCTmQEouSigUZJPVl7sW8V26EiboImL+UyXznnr1a03/YZ2BX8OlFw0n+Zlwu+EZAITZtaeRTxyA==", "dev": true, - "optional": true + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^28.1.1", + "@jest/test-result": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "@jridgewell/trace-mapping": "^0.3.13", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^28.1.1", + "jest-util": "^28.1.1", + "jest-worker": "^28.1.1", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "node_modules/@jest/reporters/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, - "optional": true - }, - "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 + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "node_modules/@jest/reporters/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, - "optional": true + "engines": { + "node": ">=8" + } }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "node_modules/@jest/reporters/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "optional": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true + "engines": { + "node": ">=8" + } }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "node_modules/@jest/reporters/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, - "optional": true + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "node_modules/@jest/schemas": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.0.2.tgz", + "integrity": "sha512-YVDJZjd4izeTDkij00vHHAymNXQ6WWsdChFRK86qck6Jpr3DCL5W3Is3vslviRlP+bLuMYRLbdp98amMvqudhA==", "dev": true, - "optional": true - }, - "atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" + "dependencies": { + "@sinclair/typebox": "^0.23.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "node_modules/@jest/source-map": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", + "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", "dev": true, - "requires": { - "object.assign": "^4.1.0" + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.13", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "babel-plugin-module-resolver": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.0.0.tgz", - "integrity": "sha512-3pdEq3PXALilSJ6dnC4wMWr0AZixHRM4utpdpBR9g5QG7B7JwWyukQv7a9hVxkbGFl+nQbrHDqqQOIBtTXTP/Q==", + "node_modules/@jest/test-result": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.1.tgz", + "integrity": "sha512-hPmkugBktqL6rRzwWAtp1JtYT4VHwv8OQ+9lE5Gymj6dHzubI/oJHMUpPOt8NrdVWSrz9S7bHjJUmv2ggFoUNQ==", "dev": true, - "requires": { - "find-babel-config": "^1.2.0", - "glob": "^7.1.6", - "pkg-up": "^3.1.0", - "reselect": "^4.0.0", - "resolve": "^1.13.1" + "dependencies": { + "@jest/console": "^28.1.1", + "@jest/types": "^28.1.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.1.tgz", + "integrity": "sha512-nuL+dNSVMcWB7OOtgb0EGH5AjO4UBCt68SLP08rwmC+iRhyuJWS9MtZ/MpipxFwKAlHFftbMsydXqWre8B0+XA==", + "dev": true, "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - } + "@jest/test-result": "^28.1.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "node_modules/@jest/test-sequencer/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" + } }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "node_modules/@jest/transform": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.2.tgz", + "integrity": "sha512-3o+lKF6iweLeJFHBlMJysdaPbpoMmtbHEFsjzSv37HIq/wWt5ijTeO2Yf7MO5yyczCopD507cNwNLeX8Y/CuIg==", "dev": true, - "optional": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "@babel/core": "^7.11.6", + "@jest/types": "^28.1.1", + "@jridgewell/trace-mapping": "^0.3.13", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.1", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "bcrypt": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", - "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "^3.1.0" + "node_modules/@jest/transform/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" } }, - "bigi": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", - "integrity": "sha1-nGZalfiLiwj8Bc/XMfVhhZ1yWCU=" + "node_modules/@jest/transform/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" + } }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true + "node_modules/@jest/transform/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" + } }, - "boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "node_modules/@jest/transform/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, - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, "dependencies": { - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "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 - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", + "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/@jest/types": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.1.tgz", + "integrity": "sha512-vRXVqSg1VhDnB8bWcmvLzmg0Bt9CRKVgHPXqYwvWMX3TvAjeO+nRuK6+VdTKCtWOvYlmkF/HqNAL/z+N3B53Kw==", "dev": true, - "requires": { - "fill-range": "^7.0.1" + "dependencies": { + "@jest/schemas": "^28.0.2", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "node_modules/@jest/types/node_modules/@types/yargs": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", + "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - }, "dependencies": { - "caniuse-lite": { - "version": "1.0.30001230", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz", - "integrity": "sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.738", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.738.tgz", - "integrity": "sha512-vCMf4gDOpEylPSLPLSwAEsz+R3ShP02Y3cAKMZvTqule3XcPp7tgc/0ESI7IS6ZeyBlGClE50N53fIOkcIVnpw==", - "dev": true - }, - "node-releases": { - "version": "1.1.72", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", - "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==", - "dev": true - } + "@types/yargs-parser": "*" } }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "node_modules/@jest/types/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" + } }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "node_modules/@jest/types/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, - "optional": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "engines": { + "node": ">=8" } }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "node_modules/@jest/types/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, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } }, - "canvas": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz", - "integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.14.0", - "simple-get": "^3.0.3" + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", + "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", + "dependencies": { + "detect-libc": "^1.0.3", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.1", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "rimraf": "^3.0.2", + "semver": "^7.3.4", + "tar": "^6.1.0" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dependencies": { - "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==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "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==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - } + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "node_modules/@nicolo-ribaudo/chokidar-2": { + "version": "2.1.8-no-fsevents.3", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", + "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "optional": true + }, + "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": { - "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, - "requires": { - "is-glob": "^4.0.1" - } - } + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + "node_modules/@runejs/common": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@runejs/common/-/common-2.0.1.tgz", + "integrity": "sha512-mSWUVDELsWJ7Oi6MeGk6iQvJAI5TShpy8J7BwSym5cfdUoRm21884X+/p9D/C9PXTT//yRbvpq0CGK9EazMfNw==", + "dependencies": { + "compressjs": "^1.0.3", + "js-yaml": "^3.14.1", + "pino": "^6.14.0", + "pino-pretty": "^4.8.0", + "sonic-boom": "^2.6.0", + "tslib": "^2.3.1" + }, + "peerDependencies": { + "tslib": ">=2.3.0", + "typescript": ">=4.5.0" + } }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true + "node_modules/@runejs/common/node_modules/sonic-boom": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.6.0.tgz", + "integrity": "sha512-6xYZFRmDEtxGqfOKcDQ4cPLrNa0SPEDI+wlzDAHowXE6YV42NeXqg9mP2KkiM8JVu3lHfZ2iQKYlGOz+kTpphg==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "node_modules/@runejs/eslint-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@runejs/eslint-config/-/eslint-config-1.0.0.tgz", + "integrity": "sha512-Z4yELzMWGQ75ihZgPMIEUKucc1X5GvIu8ZYDxjKnjcCkTT3VvMRZ4mFvXxmrXy5kip2X/PR3Sklw6uIR9UCkBg==", "dev": true, - "optional": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "peerDependencies": { + "@typescript-eslint/eslint-plugin": ">=4.22.0", + "@typescript-eslint/parser": ">=4.22.0", + "eslint": ">=7", + "typescript": ">=4" + } + }, + "node_modules/@runejs/filestore": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@runejs/filestore/-/filestore-0.16.0.tgz", + "integrity": "sha512-Vf2R2HqN8pQkxf0C+1OgzjL8twa4LRZ4RmHF4dcCYvXoUSHzja34U0igLhBJAXfrpRHkiuQVT+p2ipLoAPMYLQ==", + "dependencies": { + "@runejs/common": "^2.0.1", + "canvas": "^2.9.0", + "pngjs": "^6.0.0", + "properties-parser": "^0.3.1", + "seek-bzip": "^1.0.6", + "tslib": "^2.3.1" }, + "peerDependencies": { + "@runejs/common": ">=2.0.1", + "tslib": ">=2.3.0", + "typescript": ">=4.5.0" + } + }, + "node_modules/@runejs/login-server": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@runejs/login-server/-/login-server-2.0.0.tgz", + "integrity": "sha512-oAl4MfCw7oo/w6uda6YKUGs/RRrTpm8J31X4Z2tVAwY2l5QTWAsJicV/QJLYYnsO/RKxHDiA1dM3PGXVkKvimw==", "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } + "@runejs/common": "^2.0.1", + "bcrypt": "^5.0.1", + "bigi": "^1.4.2", + "source-map-support": "^0.5.21", + "tslib": "^2.3.1" + }, + "peerDependencies": { + "@runejs/common": ">=2.0.1", + "tslib": ">=2.3.0", + "typescript": ">=4.5.0" } }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true + "node_modules/@runejs/store": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@runejs/store/-/store-1.0.0-beta.1.tgz", + "integrity": "sha512-W4ZD1xOlQ7AS7bfjDPdog7Wea6WSdE8o/8x9WuzguhkTSK/ePX9pB4Yxj3PuMM/mv7pGhtX5xDxi/Aiw9f4bZw==", + "dependencies": { + "@runejs/common": "^2.0.1", + "graceful-fs": "^4.2.0", + "json5": "^2.2.0", + "reflect-metadata": "^0.1.13", + "sqlite": "^4.0.23", + "tslib": "^2.3.1", + "typeorm": "^0.2.44", + "yargs": "^17.3.1" + }, + "peerDependencies": { + "@runejs/common": ">=2.0.1", + "graceful-fs": ">=4.2.0", + "tslib": ">=2.3.0", + "typescript": ">=4.5.0" + } }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "requires": { + "node_modules/@runejs/store/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.0", - "wrap-ansi": "^6.2.0" + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" + "node_modules/@runejs/store/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" } }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "node_modules/@runejs/store/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" + } }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "node_modules/@runejs/store/node_modules/yargs": { + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "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/@runejs/store/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/@runejs/update-server": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@runejs/update-server/-/update-server-1.3.0.tgz", + "integrity": "sha512-6QEpEyh0znJDEWVFQlLbT8eCRkG1dKq3RnDAn0ILtDlTTD4BFEHdDGruiFc0BnH6SxsH0dzAtOV329szb2Im9w==", + "dependencies": { + "@runejs/common": "^2.0.1", + "@runejs/filestore": "^0.16.0", + "crc-32": "^1.2.1", + "source-map-support": "^0.5.21", + "tslib": "^2.3.1" + }, + "peerDependencies": { + "@runejs/common": ">=2.0.1", + "@runejs/filestore": ">=0.16.0", + "tslib": ">=2.3.0", + "typescript": ">=4.5.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz", + "integrity": "sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, - "optional": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "dependencies": { + "type-detect": "4.0.8" } }, - "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==", - "requires": { - "color-name": "~1.1.4" + "node_modules/@sinonjs/fake-timers": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", + "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" } }, - "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/@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", "dev": true }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true }, - "commondir": { + "node_modules/@tsconfig/node14": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", "dev": true }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true, - "optional": true + "node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "node_modules/@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } }, - "concurrently": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.1.0.tgz", - "integrity": "sha512-9ViZMu3OOCID3rBgU31mjBftro2chOop0G2u1olq1OuwRBVRw/GxHTg80TVJBUTJfoswMmEUeuOg1g1yu1X2dA==", + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "28.1.4", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-28.1.4.tgz", + "integrity": "sha512-telv6G5N7zRJiLcI3Rs3o+ipZ28EnE+7EvF0pSrt2pZOMnAVI/f+6/LucDxOvcBcTeTL3JMF744BbVQAVBUQRA==", + "dev": true, + "dependencies": { + "jest-matcher-utils": "^28.0.0", + "pretty-format": "^28.0.0" + } + }, + "node_modules/@types/js-yaml": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.7.tgz", + "integrity": "sha512-S6+8JAYTE1qdsc9HMVsfY7+SgSuUU/Tp6TYTmITW0PZxiyIMvol3Gy//y69Wkhs0ti4py5qgR3uZH6uz/DNzJQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.30.tgz", + "integrity": "sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.179", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.179.tgz", + "integrity": "sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "16.11.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", + "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==", + "dev": true + }, + "node_modules/@types/prettier": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", + "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.10.tgz", + "integrity": "sha512-BgeaZuElf7DEYZhWYDTc/XcLZXdVgFkVSTa13BqKvbnmUrxr3TJFKofUxCtDO9UQOdhnV+HPOESdHiHKZOJV1A==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", + "dev": true + }, + "node_modules/@types/zen-observable": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", + "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^4.0.0", + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", + "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", + "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "debug": "^4.3.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", + "dev": true, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", + "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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==" + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "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/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.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==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "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/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "engines": { + "node": ">=0.4.2" + } + }, + "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-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dependencies": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/args": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/args/-/args-5.0.1.tgz", + "integrity": "sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==", + "dependencies": { + "camelcase": "5.0.0", + "chalk": "2.4.2", + "leven": "2.1.0", + "mri": "1.1.4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/args/node_modules/camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/args/node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "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/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/babel-jest": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.2.tgz", + "integrity": "sha512-pfmoo6sh4L/+5/G2OOfQrGJgvH7fTa1oChnuYH2G/6gA+JwDvO8PELwvwnofKBMNrQsam0Wy/Rw+QSrBNewq2Q==", + "dev": true, + "dependencies": { + "@jest/transform": "^28.1.2", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^28.1.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/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/babel-jest/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/babel-jest/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/babel-jest/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/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.1.tgz", + "integrity": "sha512-NovGCy5Hn25uMJSAU8FaHqzs13cFoOI4lhIujiepssjCKRsAo3TA734RDWSGxuFTsUJXerYOqQQodlxgmtqbzw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/babel-plugin-module-resolver": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz", + "integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==", + "dev": true, + "dependencies": { + "find-babel-config": "^1.2.0", + "glob": "^7.1.6", + "pkg-up": "^3.1.0", + "reselect": "^4.0.0", + "resolve": "^1.13.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.1.tgz", + "integrity": "sha512-FCq9Oud0ReTeWtcneYf/48981aTfXYuB9gbU4rBNNJVBSQ6ssv7E6v/qvbBxtOWwZFXjLZwpg+W3q7J6vhH25g==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^28.1.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "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": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bigi": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", + "integrity": "sha1-nGZalfiLiwj8Bc/XMfVhhZ1yWCU=" + }, + "node_modules/binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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==", + "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/browserslist": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", + "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001312", + "electron-to-chromium": "^1.4.71", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001312", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", + "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/canvas": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.0.tgz", + "integrity": "sha512-0l93g7uxp7rMyr7H+XRQ28A3ud0dKIUTIEkUe1Dxh4rjUYN7B93+SjC3r1PDKA18xcQN87OFGgUnyw7LSgNLSQ==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.15.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "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/chalk/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/chalk/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/chalk/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true + }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/cli-highlight/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/cli-highlight/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/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/cli-highlight/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/cli-highlight/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/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true + }, + "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/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/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/compressjs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/compressjs/-/compressjs-1.0.3.tgz", + "integrity": "sha1-ldt03VuQOM+AvKMhqw7eJxtJWbY=", + "dependencies": { + "amdefine": "~1.0.0", + "commander": "~2.8.1" + }, + "bin": { + "compressjs": "bin/compressjs" + } + }, + "node_modules/compressjs/node_modules/commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/concurrently": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.3.0.tgz", + "integrity": "sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "date-fns": "^2.0.1", + "lodash": "^4.17.15", + "read-pkg": "^4.0.1", + "rxjs": "^6.5.2", + "spawn-command": "^0.0.2-1", + "supports-color": "^6.1.0", + "tree-kill": "^1.2.2", + "yargs": "^13.3.0" + }, + "bin": { + "concurrently": "bin/concurrently.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/concurrently/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/concurrently/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==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/concurrently/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/concurrently/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==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/concurrently/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/concurrently/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/concurrently/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/concurrently/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/concurrently/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/concurrently/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/concurrently/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/concurrently/node_modules/rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/concurrently/node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/concurrently/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/concurrently/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==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/concurrently/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/concurrently/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.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": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/concurrently/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "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": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/core-js": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", + "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz", + "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==", + "dev": true, + "dependencies": { + "browserslist": "^4.19.1", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "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": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/crc-32": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", + "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", + "dependencies": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.3.1" + }, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/date-fns": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.9.0.tgz", + "integrity": "sha512-khbFLu/MlzLjEzy9Gh8oY1hNt/Dvxw3J6Rbc28cVoYWQaC1S3YI4xwkF9ZWcjDLscbZlY9hISMr66RFzZagLsA==", + "dev": true + }, + "node_modules/dateformat": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz", + "integrity": "sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "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": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", + "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "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/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.73", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz", + "integrity": "sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "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==" + }, + "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/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/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/eslint/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/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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/eslint/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/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/eslint/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/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "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/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "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/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/expect": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.1.tgz", + "integrity": "sha512-/AANEwGL0tWBwzLNOvO0yUdy2D52jVdNXppOqswC49sxMN2cPWsGCQdzuIf9tj6hHoBQzNvx75JUYuQAckPo3w==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^28.1.1", + "jest-get-type": "^28.0.2", + "jest-matcher-utils": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-util": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "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==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "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-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==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fast-redact": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.1.tgz", + "integrity": "sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", + "integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==" + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "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/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-babel-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", + "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==", + "dev": true, + "dependencies": { + "json5": "^0.5.1", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-babel-config/node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/find-babel-config/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "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==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatstr": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", + "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" + }, + "node_modules/flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "dev": true + }, + "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==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "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.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.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-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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": "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/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/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/globby/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/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "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": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "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/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.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.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "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/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/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/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "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/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": 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-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "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": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "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-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/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-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.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.2.tgz", + "integrity": "sha512-Tuf05DwLeCh2cfWCQbcz9UxldoDyiR1E9Igaei5khjonKncYdc6LDfynKCEWozK0oLE3GD+xKAo2u8x/0s6GOg==", + "dev": true, + "dependencies": { + "@jest/core": "^28.1.2", + "@jest/types": "^28.1.1", + "import-local": "^3.0.2", + "jest-cli": "^28.1.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.0.2.tgz", + "integrity": "sha512-QX9u+5I2s54ZnGoMEjiM2WeBvJR2J7w/8ZUmH2um/WLAuGAYFQcsVXY9+1YL6k0H/AGUdH8pXUAv6erDqEsvIA==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-circus": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.2.tgz", + "integrity": "sha512-E2vdPIJG5/69EMpslFhaA46WkcrN74LI5V/cSJ59L7uS8UNoXbzTxmwhpi9XrIL3zqvMt5T0pl5k2l2u2GwBNQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^28.1.2", + "@jest/expect": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/types": "^28.1.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^28.1.1", + "jest-matcher-utils": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-runtime": "^28.1.2", + "jest-snapshot": "^28.1.2", + "jest-util": "^28.1.1", + "pretty-format": "^28.1.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-circus/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/jest-circus/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/jest-circus/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/jest-circus/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/jest-cli": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.2.tgz", + "integrity": "sha512-l6eoi5Do/IJUXAFL9qRmDiFpBeEJAnjJb1dcd9i/VWfVWbp3mJhuH50dNtX67Ali4Ecvt4eBkWb4hXhPHkAZTw==", + "dev": true, + "dependencies": { + "@jest/core": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/types": "^28.1.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^28.1.2", + "jest-util": "^28.1.1", + "jest-validate": "^28.1.1", + "prompts": "^2.0.1", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/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/jest-cli/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/jest-cli/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/jest-cli/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/jest-cli/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==", + "dev": true, + "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/jest-cli/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "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.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-config": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.2.tgz", + "integrity": "sha512-g6EfeRqddVbjPVBVY4JWpUY4IvQoFRIZcv4V36QkqzE0IGhEC/VkugFeBMAeUE7PRgC8KJF0yvJNDeQRbamEVA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^28.1.1", + "@jest/types": "^28.1.1", + "babel-jest": "^28.1.2", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^28.1.2", + "jest-environment-node": "^28.1.2", + "jest-get-type": "^28.0.2", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.1", + "jest-runner": "^28.1.2", + "jest-util": "^28.1.1", + "jest-validate": "^28.1.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^28.1.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/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/jest-config/node_modules/ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", + "dev": true + }, + "node_modules/jest-config/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/jest-config/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-config/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/jest-config/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/jest-config/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/jest-diff": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.1.tgz", + "integrity": "sha512-/MUUxeR2fHbqHoMMiffe/Afm+U8U4olFRJ0hiVG2lZatPJcnGxx292ustVu7bULhjV65IYMxRdploAKLbcrsyg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-diff/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/jest-diff/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/jest-diff/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/jest-docblock": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", + "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-each": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.1.tgz", + "integrity": "sha512-A042rqh17ZvEhRceDMi784ppoXR7MWGDEKTXEZXb4svt0eShMZvijGxzKsx+yIjeE8QYmHPrnHiTSQVhN4nqaw==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.1", + "chalk": "^4.0.0", + "jest-get-type": "^28.0.2", + "jest-util": "^28.1.1", + "pretty-format": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-each/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/jest-each/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/jest-each/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/jest-environment-node": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.2.tgz", + "integrity": "sha512-oYsZz9Qw27XKmOgTtnl0jW7VplJkN2oeof+SwAwKFQacq3CLlG9u4kTGuuLWfvu3J7bVutWlrbEQMOCL/jughw==", + "dev": true, + "dependencies": { + "@jest/environment": "^28.1.2", + "@jest/fake-timers": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/node": "*", + "jest-mock": "^28.1.1", + "jest-util": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.1.tgz", + "integrity": "sha512-ZrRSE2o3Ezh7sb1KmeLEZRZ4mgufbrMwolcFHNRSjKZhpLa8TdooXOOFlSwoUzlbVs1t0l7upVRW2K7RWGHzbQ==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.1", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.1", + "jest-worker": "^28.1.1", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.1.tgz", + "integrity": "sha512-4jvs8V8kLbAaotE+wFR7vfUGf603cwYtFf1/PYEsyX2BAjSzj8hQSVTP6OWzseTl0xL6dyHuKs2JAks7Pfubmw==", + "dev": true, + "dependencies": { + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.1.tgz", + "integrity": "sha512-NPJPRWrbmR2nAJ+1nmnfcKKzSwgfaciCCrYZzVnNoxVoyusYWIjkBMNvu0RHJe7dNj4hH3uZOPZsQA+xAYWqsw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-matcher-utils/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/jest-matcher-utils/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/jest-matcher-utils/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/jest-message-util": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.1.tgz", + "integrity": "sha512-xoDOOT66fLfmTRiqkoLIU7v42mal/SqwDKvfmfiWAdJMSJiU+ozgluO7KbvoAgiwIrrGZsV7viETjc8GNrA/IQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/jest-message-util/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/jest-message-util/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/jest-message-util/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/jest-message-util/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/jest-mock": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.1.tgz", + "integrity": "sha512-bDCb0FjfsmKweAvE09dZT59IMkzgN0fYBH6t5S45NoJfd2DHkS3ySG2K+hucortryhO3fVuXdlxWcbtIuV/Skw==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.1", + "@types/node": "*" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.1.tgz", + "integrity": "sha512-/d1UbyUkf9nvsgdBildLe6LAD4DalgkgZcKd0nZ8XUGPyA/7fsnaQIlKVnDiuUXv/IeZhPEDrRJubVSulxrShA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^28.1.1", + "jest-validate": "^28.1.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.2.tgz", + "integrity": "sha512-OXw4vbOZuyRTBi3tapWBqdyodU+T33ww5cPZORuTWkg+Y8lmsxQlVu3MWtJh6NMlKRTHQetF96yGPv01Ye7Mbg==", + "dev": true, + "dependencies": { + "jest-regex-util": "^28.0.2", + "jest-snapshot": "^28.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-resolve/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/jest-resolve/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/jest-resolve/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/jest-resolve/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/jest-runner": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.2.tgz", + "integrity": "sha512-6/k3DlAsAEr5VcptCMdhtRhOoYClZQmxnVMZvZ/quvPGRpN7OBQYPIC32tWSgOnbgqLXNs5RAniC+nkdFZpD4A==", + "dev": true, + "dependencies": { + "@jest/console": "^28.1.1", + "@jest/environment": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "graceful-fs": "^4.2.9", + "jest-docblock": "^28.1.1", + "jest-environment-node": "^28.1.2", + "jest-haste-map": "^28.1.1", + "jest-leak-detector": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-resolve": "^28.1.1", + "jest-runtime": "^28.1.2", + "jest-util": "^28.1.1", + "jest-watcher": "^28.1.1", + "jest-worker": "^28.1.1", + "source-map-support": "0.5.13", + "throat": "^6.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-runner/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/jest-runner/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/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runner/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/jest-runtime": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.2.tgz", + "integrity": "sha512-i4w93OsWzLOeMXSi9epmakb2+3z0AchZtUQVF1hesBmcQQy4vtaql5YdVe9KexdJaVRyPDw8DoBR0j3lYsZVYw==", + "dev": true, + "dependencies": { + "@jest/environment": "^28.1.2", + "@jest/fake-timers": "^28.1.2", + "@jest/globals": "^28.1.2", + "@jest/source-map": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-mock": "^28.1.1", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.1", + "jest-snapshot": "^28.1.2", + "jest-util": "^28.1.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-runtime/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/jest-runtime/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/jest-runtime/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/jest-runtime/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/jest-runtime/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/jest-snapshot": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.2.tgz", + "integrity": "sha512-wzrieFttZYfLvrCVRJxX+jwML2YTArOUqFpCoSVy1QUapx+LlV9uLbV/mMEhYj4t7aMeE9aSQFHSvV/oNoDAMA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/babel__traverse": "^7.0.6", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^28.1.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^28.1.1", + "jest-get-type": "^28.0.2", + "jest-haste-map": "^28.1.1", + "jest-matcher-utils": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-util": "^28.1.1", + "natural-compare": "^1.4.0", + "pretty-format": "^28.1.1", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-snapshot/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/jest-snapshot/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/jest-snapshot/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/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/jest-util": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.1.tgz", + "integrity": "sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-util/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/jest-util/node_modules/ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", + "dev": true + }, + "node_modules/jest-util/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/jest-util/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/jest-validate": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.1.tgz", + "integrity": "sha512-Kpf6gcClqFCIZ4ti5++XemYJWUPCFUW+N2gknn+KgnDf549iLul3cBuKVe1YcWRlaF8tZV8eJCap0eECOEE3Ug==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^28.0.2", + "leven": "^3.1.0", + "pretty-format": "^28.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-validate/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/jest-validate/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/jest-validate/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/jest-validate/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/jest-watcher": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.1.tgz", + "integrity": "sha512-RQIpeZ8EIJMxbQrXpJQYIIlubBnB9imEHsxxE41f54ZwcqWLysL/A0ZcdMirf+XsMn3xfphVQVV4EW0/p7i7Ug==", + "dev": true, + "dependencies": { + "@jest/test-result": "^28.1.1", + "@jest/types": "^28.1.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watcher/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/jest-watcher/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/jest-watcher/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/jest-worker": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.1.tgz", + "integrity": "sha512-Au7slXB08C6h+xbJPp7VIb6U0XX5Kc9uel/WFc6/rcTzGiaVCBRngBExSYuXSLFPULPSYU3cJ3ybS988lNFQhQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-worker/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/jest-worker/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/jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/joycon": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-2.2.5.tgz", + "integrity": "sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ==", + "engines": { + "node": ">=6" + } + }, + "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": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "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-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "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==", + "dev": true + }, + "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": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz", + "integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "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==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "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.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "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==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "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/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==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": 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.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "engines": { + "node": ">=8" + }, + "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==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mri": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz", + "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==", + "engines": { + "node": ">=4" + } + }, + "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==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, + "node_modules/node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "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-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true + }, + "node_modules/nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "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/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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==", + "dependencies": { + "p-limit": "^2.2.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==", + "engines": { + "node": ">=6" + } + }, + "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/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "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==", + "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": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "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/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/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pino": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz", + "integrity": "sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==", + "dependencies": { + "fast-redact": "^3.0.0", + "fast-safe-stringify": "^2.0.8", + "flatstr": "^1.0.12", + "pino-std-serializers": "^3.1.0", + "process-warning": "^1.0.0", + "quick-format-unescaped": "^4.0.3", + "sonic-boom": "^1.0.2" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-pretty": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-4.8.0.tgz", + "integrity": "sha512-mhQfHG4rw5ZFpWL44m0Utjo4GC2+HMfdNvxyA8lLw0sIqn6fCf7uQe6dPckUcW/obly+OQHD7B/MTso6LNizYw==", + "dependencies": { + "@hapi/bourne": "^2.0.0", + "args": "^5.0.1", + "chalk": "^4.0.0", + "dateformat": "^4.5.1", + "fast-safe-stringify": "^2.0.7", + "jmespath": "^0.15.0", + "joycon": "^2.2.5", + "pump": "^3.0.0", + "readable-stream": "^3.6.0", + "rfdc": "^1.3.0", + "split2": "^3.1.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/pino-pretty/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pino-pretty/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pino-pretty/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==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pino-pretty/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pino-std-serializers": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", + "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==" + }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "engines": { + "node": ">=12.13.0" + } + }, + "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/pretty-format": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.1.tgz", + "integrity": "sha512-wwJbVTGFHeucr5Jw2bQ9P+VYHyLdAqedFLEkdQUVaBF/eiidDwH5OpilINq4mEfhbCjLnirt6HTTDhv1HaTIQw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.0.2", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/printj": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", + "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==", + "bin": { + "printj": "bin/printj.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "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==" + }, + "node_modules/process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" + }, + "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/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/properties-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/properties-parser/-/properties-parser-0.3.1.tgz", + "integrity": "sha1-ExbpU5/7/ZOEXjabIRAiq9R4dxo=", + "dependencies": { + "string.prototype.codepointat": "^0.2.0" + }, + "engines": { + "node": ">= 0.3.1" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "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": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/quadtree-lib": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/quadtree-lib/-/quadtree-lib-1.0.9.tgz", + "integrity": "sha512-2hFsbM1+gqVkNafxAEjv/XD9VO7s4urGkV/Wdo36YoQQ7q4i6IgcAcVcmbWLOtVcIj7XYQmUl1QUOBr59FDbsA==" + }, + "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/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/read-pkg": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", + "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "dev": true, + "dependencies": { + "normalize-package-data": "^2.3.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-pkg/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "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/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/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regexpu-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "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==" + }, + "node_modules/reselect": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", + "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "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-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/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/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.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "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/rxjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz", + "integrity": "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "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==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "dependencies": { + "commander": "^2.8.1" + }, + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "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": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dev": true, + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/sonic-boom": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", + "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "flatstr": "^1.0.12" + } + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/sqlite": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-4.1.2.tgz", + "integrity": "sha512-FlBG51gHbux5vPjwnoqFEghNGvnTMTbHyiI09U3qFTQs9AtWuwd4i++6+WCusCXKrVdIDLzfdGekrolr3m4U4A==" + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.codepointat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", + "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/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/supports-hyperlinks/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/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/table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", + "dev": true + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "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": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "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/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-node": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.5.0.tgz", + "integrity": "sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "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-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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/typeorm": { + "version": "0.2.45", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.2.45.tgz", + "integrity": "sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA==", + "dependencies": { + "@sqltools/formatter": "^1.2.2", + "app-root-path": "^3.0.0", + "buffer": "^6.0.3", + "chalk": "^4.1.0", + "cli-highlight": "^2.1.11", + "debug": "^4.3.1", + "dotenv": "^8.2.0", + "glob": "^7.1.6", + "js-yaml": "^4.0.0", + "mkdirp": "^1.0.4", + "reflect-metadata": "^0.1.13", + "sha.js": "^2.4.11", + "tslib": "^2.1.0", + "uuid": "^8.3.2", + "xml2js": "^0.4.23", + "yargs": "^17.0.1", + "zen-observable-ts": "^1.0.0" + }, + "bin": { + "typeorm": "cli.js" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@sap/hana-client": "^2.11.14", + "better-sqlite3": "^7.1.2", + "hdb-pool": "^0.1.6", + "ioredis": "^4.28.3", + "mongodb": "^3.6.0", + "mssql": "^6.3.1", + "mysql2": "^2.2.5", + "oracledb": "^5.1.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.2", + "typeorm-aurora-data-api-driver": "^2.0.0" + }, + "peerDependenciesMeta": { + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "hdb-pool": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm/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==" + }, + "node_modules/typeorm/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/typeorm/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/typeorm/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/typeorm/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==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/typeorm/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/typeorm/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==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/typeorm/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/typeorm/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/typeorm/node_modules/yargs": { + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "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/typeorm/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/typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "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/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", + "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", + "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "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==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==" + }, + "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/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "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/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "node_modules/zen-observable-ts": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", + "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", + "dependencies": { + "@types/zen-observable": "0.8.3", + "zen-observable": "0.8.15" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.0" + } + }, + "@babel/cli": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.17.6.tgz", + "integrity": "sha512-l4w608nsDNlxZhiJ5tE3DbNmr61fIKMZ6fTBo171VEFuFMIYuJ3mHRhTLEkKKyvx2Mizkkv/0a8OJOnZqkKYNA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.4", + "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", + "chokidar": "^3.4.0", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", + "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", + "dev": true + }, + "@babel/core": { + "version": "7.17.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz", + "integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helpers": "^7.17.2", + "@babel/parser": "^7.17.3", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", + "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", + "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.16.4", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.17.5", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz", + "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", + "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", + "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", + "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz", + "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz", + "integrity": "sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" + } + }, + "@babel/helper-replace-supers": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", + "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-simple-access": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", + "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" + } + }, + "@babel/helpers": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", + "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.0", + "@babel/types": "^7.17.0" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/node": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.16.8.tgz", + "integrity": "sha512-V2dopEtPUL4LD+e8UtMIZB6BbsmMsS/7E1ZAvWNINzBfi7Cf3X9MLCpzHVZT4HeeF1lQl72IRtqqVt2RUImwyA==", + "dev": true, + "requires": { + "@babel/register": "^7.16.8", + "commander": "^4.0.1", + "core-js": "^3.20.2", + "node-environment-flags": "^1.0.5", + "regenerator-runtime": "^0.13.4", + "v8flags": "^3.1.1" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + } + } + }, + "@babel/parser": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", + "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", + "dev": true + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", + "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", + "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.7" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", + "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", + "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", + "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.17.6", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", + "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", + "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", + "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", + "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", + "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.17.0", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.16.7" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", + "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", + "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.10", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", + "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", + "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", + "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", + "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", + "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", + "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", + "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", + "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz", + "integrity": "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", + "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", + "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", + "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", + "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz", + "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz", + "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", + "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", + "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", + "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", + "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", + "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", + "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", + "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", + "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", + "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", + "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-typescript": "^7.16.7" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/preset-env": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", + "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.16.8", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-async-generator-functions": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-class-static-block": "^7.16.7", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.16.7", + "@babel/plugin-proposal-json-strings": "^7.16.7", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.16.7", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-private-methods": "^7.16.11", + "@babel/plugin-proposal-private-property-in-object": "^7.16.7", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.16.7", + "@babel/plugin-transform-async-to-generator": "^7.16.8", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.16.7", + "@babel/plugin-transform-classes": "^7.16.7", + "@babel/plugin-transform-computed-properties": "^7.16.7", + "@babel/plugin-transform-destructuring": "^7.16.7", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.16.7", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.16.7", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.16.7", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.16.7", + "@babel/plugin-transform-modules-commonjs": "^7.16.8", + "@babel/plugin-transform-modules-systemjs": "^7.16.7", + "@babel/plugin-transform-modules-umd": "^7.16.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", + "@babel/plugin-transform-new-target": "^7.16.7", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.16.7", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.16.7", + "@babel/plugin-transform-reserved-words": "^7.16.7", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.16.7", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.16.7", + "@babel/plugin-transform-typeof-symbol": "^7.16.7", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.16.8", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.20.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", + "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-typescript": "^7.16.7" + } + }, + "@babel/register": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.0.tgz", + "integrity": "sha512-UNZsMAZ7uKoGHo1HlEXfteEOYssf64n/PNLHGqOKq/bgYcu/4LrQWAHJwSCb3BRZK8Hi5gkJdRcwrGTO2wtRCg==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.5", + "source-map-support": "^0.5.16" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + } + } + }, + "@babel/runtime": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz", + "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + } + } + }, + "@babel/traverse": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", + "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.3", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + } + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "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 + } + } + }, + "@hapi/bourne": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz", + "integrity": "sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg==" + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "@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, + "requires": { + "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" + }, + "dependencies": { + "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 + } + } + }, + "@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 + }, + "@jest/console": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.1.tgz", + "integrity": "sha512-0RiUocPVFEm3WRMOStIHbRWllG6iW6E3/gUPnf4lkrVFyXIIDeCe+vlKeYyFOMhB2EPE6FLFCNADSOOQMaqvyA==", + "dev": true, + "requires": { + "@jest/types": "^28.1.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.1", + "jest-util": "^28.1.1", + "slash": "^3.0.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/core": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.2.tgz", + "integrity": "sha512-Xo4E+Sb/nZODMGOPt2G3cMmCBqL4/W2Ijwr7/mrXlq4jdJwcFQ/9KrrJZT2adQRk2otVBXXOz1GRQ4Z5iOgvRQ==", + "dev": true, + "requires": { + "@jest/console": "^28.1.1", + "@jest/reporters": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^28.0.2", + "jest-config": "^28.1.2", + "jest-haste-map": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.1", + "jest-resolve-dependencies": "^28.1.2", + "jest-runner": "^28.1.2", + "jest-runtime": "^28.1.2", + "jest-snapshot": "^28.1.2", + "jest-util": "^28.1.1", + "jest-validate": "^28.1.1", + "jest-watcher": "^28.1.1", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.1", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", + "dev": true + }, + "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 + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/environment": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.2.tgz", + "integrity": "sha512-I0CR1RUMmOzd0tRpz10oUfaChBWs+/Hrvn5xYhMEF/ZqrDaaeHwS8yDBqEWCrEnkH2g+WE/6g90oBv3nKpcm8Q==", + "dev": true, + "requires": { + "@jest/fake-timers": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/node": "*", + "jest-mock": "^28.1.1" + } + }, + "@jest/expect": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.2.tgz", + "integrity": "sha512-HBzyZBeFBiOelNbBKN0pilWbbrGvwDUwAqMC46NVJmWm8AVkuE58NbG1s7DR4cxFt4U5cVLxofAoHxgvC5MyOw==", + "dev": true, + "requires": { + "expect": "^28.1.1", + "jest-snapshot": "^28.1.2" + } + }, + "@jest/expect-utils": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.1.tgz", + "integrity": "sha512-n/ghlvdhCdMI/hTcnn4qV57kQuV9OTsZzH1TTCVARANKhl6hXJqLKUkwX69ftMGpsbpt96SsDD8n8LD2d9+FRw==", + "dev": true, + "requires": { + "jest-get-type": "^28.0.2" + } + }, + "@jest/fake-timers": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.2.tgz", + "integrity": "sha512-xSYEI7Y0D5FbZN2LsCUj/EKRR1zfQYmGuAUVh6xTqhx7V5JhjgMcK5Pa0iR6WIk0GXiHDe0Ke4A+yERKE9saqg==", + "dev": true, + "requires": { + "@jest/types": "^28.1.1", + "@sinonjs/fake-timers": "^9.1.2", + "@types/node": "*", + "jest-message-util": "^28.1.1", + "jest-mock": "^28.1.1", + "jest-util": "^28.1.1" + } + }, + "@jest/globals": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.2.tgz", + "integrity": "sha512-cz0lkJVDOtDaYhvT3Fv2U1B6FtBnV+OpEyJCzTHM1fdoTsU4QNLAt/H4RkiwEUU+dL4g/MFsoTuHeT2pvbo4Hg==", + "dev": true, + "requires": { + "@jest/environment": "^28.1.2", + "@jest/expect": "^28.1.2", + "@jest/types": "^28.1.1" + } + }, + "@jest/reporters": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.2.tgz", + "integrity": "sha512-/whGLhiwAqeCTmQEouSigUZJPVl7sW8V26EiboImL+UyXznnr1a03/YZ2BX8OlFw0n+Zlwu+EZAITZtaeRTxyA==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^28.1.1", + "@jest/test-result": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "@jridgewell/trace-mapping": "^0.3.13", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^28.1.1", + "jest-util": "^28.1.1", + "jest-worker": "^28.1.1", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/schemas": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.0.2.tgz", + "integrity": "sha512-YVDJZjd4izeTDkij00vHHAymNXQ6WWsdChFRK86qck6Jpr3DCL5W3Is3vslviRlP+bLuMYRLbdp98amMvqudhA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.23.3" + } + }, + "@jest/source-map": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", + "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.13", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@jest/test-result": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.1.tgz", + "integrity": "sha512-hPmkugBktqL6rRzwWAtp1JtYT4VHwv8OQ+9lE5Gymj6dHzubI/oJHMUpPOt8NrdVWSrz9S7bHjJUmv2ggFoUNQ==", + "dev": true, + "requires": { + "@jest/console": "^28.1.1", + "@jest/types": "^28.1.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.1.tgz", + "integrity": "sha512-nuL+dNSVMcWB7OOtgb0EGH5AjO4UBCt68SLP08rwmC+iRhyuJWS9MtZ/MpipxFwKAlHFftbMsydXqWre8B0+XA==", + "dev": true, + "requires": { + "@jest/test-result": "^28.1.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.1", + "slash": "^3.0.0" + }, + "dependencies": { + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, + "@jest/transform": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.2.tgz", + "integrity": "sha512-3o+lKF6iweLeJFHBlMJysdaPbpoMmtbHEFsjzSv37HIq/wWt5ijTeO2Yf7MO5yyczCopD507cNwNLeX8Y/CuIg==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^28.1.1", + "@jridgewell/trace-mapping": "^0.3.13", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.1", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + }, + "write-file-atomic": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", + "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + } + } + }, + "@jest/types": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.1.tgz", + "integrity": "sha512-vRXVqSg1VhDnB8bWcmvLzmg0Bt9CRKVgHPXqYwvWMX3TvAjeO+nRuK6+VdTKCtWOvYlmkF/HqNAL/z+N3B53Kw==", + "dev": true, + "requires": { + "@jest/schemas": "^28.0.2", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "dependencies": { + "@types/yargs": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", + "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@mapbox/node-pre-gyp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", + "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", + "requires": { + "detect-libc": "^1.0.3", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.1", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "rimraf": "^3.0.2", + "semver": "^7.3.4", + "tar": "^6.1.0" + }, + "dependencies": { + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@nicolo-ribaudo/chokidar-2": { + "version": "2.1.8-no-fsevents.3", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", + "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", + "dev": true, + "optional": true + }, + "@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, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@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 + }, + "@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, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@runejs/common": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@runejs/common/-/common-2.0.1.tgz", + "integrity": "sha512-mSWUVDELsWJ7Oi6MeGk6iQvJAI5TShpy8J7BwSym5cfdUoRm21884X+/p9D/C9PXTT//yRbvpq0CGK9EazMfNw==", + "requires": { + "compressjs": "^1.0.3", + "js-yaml": "^3.14.1", + "pino": "^6.14.0", + "pino-pretty": "^4.8.0", + "sonic-boom": "^2.6.0", + "tslib": "^2.3.1" + }, + "dependencies": { + "sonic-boom": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.6.0.tgz", + "integrity": "sha512-6xYZFRmDEtxGqfOKcDQ4cPLrNa0SPEDI+wlzDAHowXE6YV42NeXqg9mP2KkiM8JVu3lHfZ2iQKYlGOz+kTpphg==", + "requires": { + "atomic-sleep": "^1.0.0" + } + } + } + }, + "@runejs/eslint-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@runejs/eslint-config/-/eslint-config-1.0.0.tgz", + "integrity": "sha512-Z4yELzMWGQ75ihZgPMIEUKucc1X5GvIu8ZYDxjKnjcCkTT3VvMRZ4mFvXxmrXy5kip2X/PR3Sklw6uIR9UCkBg==", + "dev": true, + "requires": {} + }, + "@runejs/filestore": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@runejs/filestore/-/filestore-0.16.0.tgz", + "integrity": "sha512-Vf2R2HqN8pQkxf0C+1OgzjL8twa4LRZ4RmHF4dcCYvXoUSHzja34U0igLhBJAXfrpRHkiuQVT+p2ipLoAPMYLQ==", + "requires": { + "@runejs/common": "^2.0.1", + "canvas": "^2.9.0", + "pngjs": "^6.0.0", + "properties-parser": "^0.3.1", + "seek-bzip": "^1.0.6", + "tslib": "^2.3.1" + } + }, + "@runejs/login-server": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@runejs/login-server/-/login-server-2.0.0.tgz", + "integrity": "sha512-oAl4MfCw7oo/w6uda6YKUGs/RRrTpm8J31X4Z2tVAwY2l5QTWAsJicV/QJLYYnsO/RKxHDiA1dM3PGXVkKvimw==", + "requires": { + "@runejs/common": "^2.0.1", + "bcrypt": "^5.0.1", + "bigi": "^1.4.2", + "source-map-support": "^0.5.21", + "tslib": "^2.3.1" + } + }, + "@runejs/store": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@runejs/store/-/store-1.0.0-beta.1.tgz", + "integrity": "sha512-W4ZD1xOlQ7AS7bfjDPdog7Wea6WSdE8o/8x9WuzguhkTSK/ePX9pB4Yxj3PuMM/mv7pGhtX5xDxi/Aiw9f4bZw==", + "requires": { + "@runejs/common": "^2.0.1", + "graceful-fs": "^4.2.0", + "json5": "^2.2.0", + "reflect-metadata": "^0.1.13", + "sqlite": "^4.0.23", + "tslib": "^2.3.1", + "typeorm": "^0.2.44", + "yargs": "^17.3.1" + }, + "dependencies": { + "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==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "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==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs": { + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "requires": { + "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" + } + }, + "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==" + } + } + }, + "@runejs/update-server": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@runejs/update-server/-/update-server-1.3.0.tgz", + "integrity": "sha512-6QEpEyh0znJDEWVFQlLbT8eCRkG1dKq3RnDAn0ILtDlTTD4BFEHdDGruiFc0BnH6SxsH0dzAtOV329szb2Im9w==", + "requires": { + "@runejs/common": "^2.0.1", + "@runejs/filestore": "^0.16.0", + "crc-32": "^1.2.1", + "source-map-support": "^0.5.21", + "tslib": "^2.3.1" + } + }, + "@sinclair/typebox": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz", + "integrity": "sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==", + "dev": true + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", + "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" + }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "28.1.4", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-28.1.4.tgz", + "integrity": "sha512-telv6G5N7zRJiLcI3Rs3o+ipZ28EnE+7EvF0pSrt2pZOMnAVI/f+6/LucDxOvcBcTeTL3JMF744BbVQAVBUQRA==", + "dev": true, + "requires": { + "jest-matcher-utils": "^28.0.0", + "pretty-format": "^28.0.0" + } + }, + "@types/js-yaml": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.7.tgz", + "integrity": "sha512-S6+8JAYTE1qdsc9HMVsfY7+SgSuUU/Tp6TYTmITW0PZxiyIMvol3Gy//y69Wkhs0ti4py5qgR3uZH6uz/DNzJQ==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "@types/json5": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.30.tgz", + "integrity": "sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.179", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.179.tgz", + "integrity": "sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w==", + "dev": true + }, + "@types/node": { + "version": "16.11.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", + "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==", + "dev": true + }, + "@types/prettier": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", + "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/uuid": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.10.tgz", + "integrity": "sha512-BgeaZuElf7DEYZhWYDTc/XcLZXdVgFkVSTa13BqKvbnmUrxr3TJFKofUxCtDO9UQOdhnV+HPOESdHiHKZOJV1A==", + "dev": true + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz", + "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", + "dev": true + }, + "@types/zen-observable": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", + "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==" + }, + "@typescript-eslint/eslint-plugin": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", + "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", + "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "debug": "^4.3.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" + } + }, + "@typescript-eslint/types": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", + "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.33.0", + "eslint-visitor-keys": "^2.0.0" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "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, + "requires": {} + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "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==", + "requires": { + "debug": "4" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "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 + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "args": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/args/-/args-5.0.1.tgz", + "integrity": "sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==", + "requires": { + "camelcase": "5.0.0", + "chalk": "2.4.2", + "leven": "2.1.0", + "mri": "1.1.4" + }, + "dependencies": { + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==" + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + } + } + }, + "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 + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" + }, + "babel-jest": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.2.tgz", + "integrity": "sha512-pfmoo6sh4L/+5/G2OOfQrGJgvH7fTa1oChnuYH2G/6gA+JwDvO8PELwvwnofKBMNrQsam0Wy/Rw+QSrBNewq2Q==", + "dev": true, + "requires": { + "@jest/transform": "^28.1.2", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^28.1.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.1.tgz", + "integrity": "sha512-NovGCy5Hn25uMJSAU8FaHqzs13cFoOI4lhIujiepssjCKRsAo3TA734RDWSGxuFTsUJXerYOqQQodlxgmtqbzw==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-plugin-module-resolver": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz", + "integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==", + "dev": true, + "requires": { + "find-babel-config": "^1.2.0", + "glob": "^7.1.6", + "pkg-up": "^3.1.0", + "reselect": "^4.0.0", + "resolve": "^1.13.1" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.1.tgz", + "integrity": "sha512-FCq9Oud0ReTeWtcneYf/48981aTfXYuB9gbU4rBNNJVBSQ6ssv7E6v/qvbBxtOWwZFXjLZwpg+W3q7J6vhH25g==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^28.1.1", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bcrypt": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + } + }, + "bigi": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", + "integrity": "sha1-nGZalfiLiwj8Bc/XMfVhhZ1yWCU=" + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", + "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001312", + "electron-to-chromium": "^1.4.71", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "caniuse-lite": { + "version": "1.0.30001312", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", + "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", + "dev": true + }, + "canvas": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.0.tgz", + "integrity": "sha512-0l93g7uxp7rMyr7H+XRQ28A3ud0dKIUTIEkUe1Dxh4rjUYN7B93+SjC3r1PDKA18xcQN87OFGgUnyw7LSgNLSQ==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.15.0", + "simple-get": "^3.0.3" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "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==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "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==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + } + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.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" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true + }, + "cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "requires": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "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==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "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==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + } + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true + }, + "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==", + "requires": { + "color-name": "~1.1.4" + } + }, + "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==" + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "compressjs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/compressjs/-/compressjs-1.0.3.tgz", + "integrity": "sha1-ldt03VuQOM+AvKMhqw7eJxtJWbY=", + "requires": { + "amdefine": "~1.0.0", + "commander": "~2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concurrently": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.3.0.tgz", + "integrity": "sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "date-fns": "^2.0.1", + "lodash": "^4.17.15", + "read-pkg": "^4.0.1", + "rxjs": "^6.5.2", + "spawn-command": "^0.0.2-1", + "supports-color": "^6.1.0", + "tree-kill": "^1.2.2", + "yargs": "^13.3.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "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==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.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": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "core-js": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", + "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", + "dev": true + }, + "core-js-compat": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz", + "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==", + "dev": true, + "requires": { + "browserslist": "^4.19.1", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc-32": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", + "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.3.1" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "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, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "date-fns": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.9.0.tgz", + "integrity": "sha512-khbFLu/MlzLjEzy9Gh8oY1hNt/Dvxw3J6Rbc28cVoYWQaC1S3YI4xwkF9ZWcjDLscbZlY9hISMr66RFzZagLsA==", + "dev": true + }, + "dateformat": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz", + "integrity": "sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==" + }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "requires": { + "mimic-response": "^2.0.0" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "diff-sequences": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", + "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true + }, + "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, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" + }, + "electron-to-chromium": { + "version": "1.4.73", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz", + "integrity": "sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA==", + "dev": true + }, + "emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "dev": true + }, + "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==" + }, + "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==", + "requires": { + "once": "^1.4.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", "dev": true, "requires": { - "chalk": "^2.4.2", - "date-fns": "^2.0.1", - "lodash": "^4.17.15", - "read-pkg": "^4.0.1", - "rxjs": "^6.5.2", - "spawn-command": "^0.0.2-1", - "supports-color": "^6.1.0", - "tree-kill": "^1.2.2", - "yargs": "^13.3.0" + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "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==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "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==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "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 }, - "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { - "tslib": "^1.9.0" + "eslint-visitor-keys": "^1.1.0" }, "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true } } }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "type-fest": "^0.20.2" } }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "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 }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.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": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "lru-cache": "^6.0.0" } }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "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 + }, + "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, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "has-flag": "^4.0.0" } } } }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "requires": { - "safe-buffer": "~5.1.1" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "optional": true - }, - "core-js": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true }, - "core-js-compat": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", - "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", "dev": true, "requires": { - "browserslist": "^4.8.5", - "semver": "7.0.0" + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" }, "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true } } }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, - "crc-32": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", - "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, "requires": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.1.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "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, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, - "date-fns": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.9.0.tgz", - "integrity": "sha512-khbFLu/MlzLjEzy9Gh8oY1hNt/Dvxw3J6Rbc28cVoYWQaC1S3YI4xwkF9ZWcjDLscbZlY9hISMr66RFzZagLsA==", + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "dateformat": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz", - "integrity": "sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + } } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "optional": true + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "expect": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.1.tgz", + "integrity": "sha512-/AANEwGL0tWBwzLNOvO0yUdy2D52jVdNXppOqswC49sxMN2cPWsGCQdzuIf9tj6hHoBQzNvx75JUYuQAckPo3w==", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "@jest/expect-utils": "^28.1.1", + "jest-get-type": "^28.0.2", + "jest-matcher-utils": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-util": "^28.1.1" } }, - "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==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "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==", "dev": true }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, - "optional": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "@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" } }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + "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==", + "dev": true }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "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, - "requires": { - "path-type": "^4.0.0" - } + "fast-redact": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.1.tgz", + "integrity": "sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A==" }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "fast-safe-stringify": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", + "integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==" + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, "requires": { - "esutils": "^2.0.2" + "reusify": "^1.0.4" } }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", "dev": true, "requires": { - "is-obj": "^2.0.0" + "bser": "2.1.1" } }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "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==" - }, - "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==", + "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, "requires": { - "once": "^1.4.0" + "flat-cache": "^3.0.4" } }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "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, "requires": { - "ansi-colors": "^4.1.1" + "to-regex-range": "^5.0.1" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "find-babel-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", + "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "json5": "^0.5.1", + "path-exists": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } } }, - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" }, "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "pify": "^4.0.1", + "semver": "^5.6.0" } } } }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatstr": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", + "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" + }, + "flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", "dev": true }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "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 - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, - "globals": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", - "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", - "dev": true, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { - "type-fest": "^0.20.2" + "number-is-nan": "^1.0.0" } }, - "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 - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "lru-cache": "^6.0.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, - "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 - }, - "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, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "has-flag": "^4.0.0" + "ansi-regex": "^2.0.0" } - }, - "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 } } }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "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 + }, + "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==" + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dev": true, "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "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 + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-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, "requires": { - "eslint-visitor-keys": "^2.0.0" + "is-glob": "^4.0.1" } }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "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 }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "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" }, "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true } } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } + "function-bind": "^1.1.1" } }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } + "parse-passwd": "^1.0.0" } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "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 }, - "exit-on-epipe": { + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "ignore-by-default": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", - "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "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, - "optional": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, - "optional": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" }, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "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, - "optional": true, "requires": { - "is-plain-object": "^2.0.4" + "find-up": "^4.0.0" } } } }, - "extglob": { + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "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, - "optional": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "binary-extensions": "^2.0.0" } }, - "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==", + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", "dev": true }, - "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "dev": true, "requires": { - "@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" - }, - "dependencies": { - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - } + "has": "^1.0.3" } }, - "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==", + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, - "fast-redact": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.1.tgz", - "integrity": "sha512-kYpn4Y/valC9MdrISg47tZOpYBNoTXKgT9GYXFpHN/jYFs+lFkPoisY+LcBODdKVMY96ATzvzsWv+ES/4Kmufw==" + "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==" }, - "fast-safe-stringify": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", - "integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==" + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true }, - "fastify-warning": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz", - "integrity": "sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw==" + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } }, - "fastq": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", - "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", + "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 + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "reusify": "^1.0.4" + "isobject": "^3.0.1" } }, - "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==", + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { - "flat-cache": "^3.0.4" + "has-symbols": "^1.0.1" } }, - "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==", + "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 + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, "requires": { - "to-regex-range": "^5.0.1" + "has-symbols": "^1.0.1" } }, - "find-babel-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", - "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==", + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", "dev": true, "requires": { - "json5": "^0.5.1", - "path-exists": "^3.0.0" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "dependencies": { - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" }, "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "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 + }, + "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, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - } - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatstr": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", - "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" - }, - "flatted": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", - "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", - "dev": true + "has-flag": "^4.0.0" + } + } + } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "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, - "optional": true + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", "dev": true, - "optional": true, "requires": { - "map-cache": "^0.2.2" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" } }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "jest": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.2.tgz", + "integrity": "sha512-Tuf05DwLeCh2cfWCQbcz9UxldoDyiR1E9Igaei5khjonKncYdc6LDfynKCEWozK0oLE3GD+xKAo2u8x/0s6GOg==", + "dev": true, "requires": { - "minipass": "^3.0.0" + "@jest/core": "^28.1.2", + "@jest/types": "^28.1.1", + "import-local": "^3.0.2", + "jest-cli": "^28.1.2" } }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "jest-changed-files": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.0.2.tgz", + "integrity": "sha512-QX9u+5I2s54ZnGoMEjiM2WeBvJR2J7w/8ZUmH2um/WLAuGAYFQcsVXY9+1YL6k0H/AGUdH8pXUAv6erDqEsvIA==", "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "requires": { + "execa": "^5.0.0", + "throat": "^6.0.1" + } }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "jest-circus": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.2.tgz", + "integrity": "sha512-E2vdPIJG5/69EMpslFhaA46WkcrN74LI5V/cSJ59L7uS8UNoXbzTxmwhpi9XrIL3zqvMt5T0pl5k2l2u2GwBNQ==", + "dev": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "@jest/environment": "^28.1.2", + "@jest/expect": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/types": "^28.1.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^28.1.1", + "jest-matcher-utils": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-runtime": "^28.1.2", + "jest-snapshot": "^28.1.2", + "jest-util": "^28.1.1", + "pretty-format": "^28.1.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "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 }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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, "requires": { - "ansi-regex": "^2.0.0" + "has-flag": "^4.0.0" } } } }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true - }, - "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==" - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "jest-cli": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.2.tgz", + "integrity": "sha512-l6eoi5Do/IJUXAFL9qRmDiFpBeEJAnjJb1dcd9i/VWfVWbp3mJhuH50dNtX67Ali4Ecvt4eBkWb4hXhPHkAZTw==", "dev": true, "requires": { - "pump": "^3.0.0" + "@jest/core": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/types": "^28.1.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^28.1.2", + "jest-util": "^28.1.1", + "jest-validate": "^28.1.1", + "prompts": "^2.0.1", + "yargs": "^17.3.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "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.0.0" + } + }, + "yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true + } } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "jest-config": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.2.tgz", + "integrity": "sha512-g6EfeRqddVbjPVBVY4JWpUY4IvQoFRIZcv4V36QkqzE0IGhEC/VkugFeBMAeUE7PRgC8KJF0yvJNDeQRbamEVA==", "dev": true, - "optional": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "requires": { - "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" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^28.1.1", + "@jest/types": "^28.1.1", + "babel-jest": "^28.1.2", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^28.1.2", + "jest-environment-node": "^28.1.2", + "jest-get-type": "^28.0.2", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.1", + "jest-runner": "^28.1.2", + "jest-util": "^28.1.1", + "jest-validate": "^28.1.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^28.1.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", + "dev": true + }, + "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 + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "jest-diff": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.1.tgz", + "integrity": "sha512-/MUUxeR2fHbqHoMMiffe/Afm+U8U4olFRJ0hiVG2lZatPJcnGxx292ustVu7bULhjV65IYMxRdploAKLbcrsyg==", "dev": true, "requires": { - "is-glob": "^4.0.1" + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "global-dirs": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", - "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "jest-docblock": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", + "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", "dev": true, "requires": { - "ini": "^1.3.5" + "detect-newline": "^3.0.0" } }, - "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 - }, - "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "jest-each": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.1.tgz", + "integrity": "sha512-A042rqh17ZvEhRceDMi784ppoXR7MWGDEKTXEZXb4svt0eShMZvijGxzKsx+yIjeE8QYmHPrnHiTSQVhN4nqaw==", "dev": true, "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" + "@jest/types": "^28.1.1", + "chalk": "^4.0.0", + "jest-get-type": "^28.0.2", + "jest-util": "^28.1.1", + "pretty-format": "^28.1.1" }, "dependencies": { - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "jest-environment-node": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.2.tgz", + "integrity": "sha512-oYsZz9Qw27XKmOgTtnl0jW7VplJkN2oeof+SwAwKFQacq3CLlG9u4kTGuuLWfvu3J7bVutWlrbEQMOCL/jughw==", "dev": true, "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "@jest/environment": "^28.1.2", + "@jest/fake-timers": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/node": "*", + "jest-mock": "^28.1.1", + "jest-util": "^28.1.1" } }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "jest-haste-map": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.1.tgz", + "integrity": "sha512-ZrRSE2o3Ezh7sb1KmeLEZRZ4mgufbrMwolcFHNRSjKZhpLa8TdooXOOFlSwoUzlbVs1t0l7upVRW2K7RWGHzbQ==", + "dev": true, "requires": { - "function-bind": "^1.1.1" + "@jest/types": "^28.1.1", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.1", + "jest-worker": "^28.1.1", + "micromatch": "^4.0.4", + "walker": "^1.0.8" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "jest-leak-detector": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.1.tgz", + "integrity": "sha512-4jvs8V8kLbAaotE+wFR7vfUGf603cwYtFf1/PYEsyX2BAjSzj8hQSVTP6OWzseTl0xL6dyHuKs2JAks7Pfubmw==", "dev": true, - "optional": true, "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.1" } }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "jest-matcher-utils": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.1.tgz", + "integrity": "sha512-NPJPRWrbmR2nAJ+1nmnfcKKzSwgfaciCCrYZzVnNoxVoyusYWIjkBMNvu0RHJe7dNj4hH3uZOPZsQA+xAYWqsw==", "dev": true, - "optional": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "chalk": "^4.0.0", + "jest-diff": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.1" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "optional": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "kind-of": { + "has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "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, - "optional": true, "requires": { - "is-buffer": "^1.1.5" + "has-flag": "^4.0.0" } } } }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "jest-message-util": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.1.tgz", + "integrity": "sha512-xoDOOT66fLfmTRiqkoLIU7v42mal/SqwDKvfmfiWAdJMSJiU+ozgluO7KbvoAgiwIrrGZsV7viETjc8GNrA/IQ==", "dev": true, "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "ms": "2.1.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "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 + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "jest-mock": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.1.tgz", + "integrity": "sha512-bDCb0FjfsmKweAvE09dZT59IMkzgN0fYBH6t5S45NoJfd2DHkS3ySG2K+hucortryhO3fVuXdlxWcbtIuV/Skw==", "dev": true, "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "@jest/types": "^28.1.1", + "@types/node": "*" } }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true + "jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "requires": {} }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", "dev": true }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "jest-resolve": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.1.tgz", + "integrity": "sha512-/d1UbyUkf9nvsgdBildLe6LAD4DalgkgZcKd0nZ8XUGPyA/7fsnaQIlKVnDiuUXv/IeZhPEDrRJubVSulxrShA==", + "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^28.1.1", + "jest-validate": "^28.1.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "jest-resolve-dependencies": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.2.tgz", + "integrity": "sha512-OXw4vbOZuyRTBi3tapWBqdyodU+T33ww5cPZORuTWkg+Y8lmsxQlVu3MWtJh6NMlKRTHQetF96yGPv01Ye7Mbg==", + "dev": true, + "requires": { + "jest-regex-util": "^28.0.2", + "jest-snapshot": "^28.1.2" + } }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "jest-runner": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.2.tgz", + "integrity": "sha512-6/k3DlAsAEr5VcptCMdhtRhOoYClZQmxnVMZvZ/quvPGRpN7OBQYPIC32tWSgOnbgqLXNs5RAniC+nkdFZpD4A==", "dev": true, "requires": { - "loose-envify": "^1.0.0" + "@jest/console": "^28.1.1", + "@jest/environment": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "graceful-fs": "^4.2.9", + "jest-docblock": "^28.1.1", + "jest-environment-node": "^28.1.2", + "jest-haste-map": "^28.1.1", + "jest-leak-detector": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-resolve": "^28.1.1", + "jest-runtime": "^28.1.2", + "jest-util": "^28.1.1", + "jest-watcher": "^28.1.1", + "jest-worker": "^28.1.1", + "source-map-support": "0.5.13", + "throat": "^6.0.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "jest-runtime": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.2.tgz", + "integrity": "sha512-i4w93OsWzLOeMXSi9epmakb2+3z0AchZtUQVF1hesBmcQQy4vtaql5YdVe9KexdJaVRyPDw8DoBR0j3lYsZVYw==", "dev": true, - "optional": true, "requires": { - "kind-of": "^3.0.2" + "@jest/environment": "^28.1.2", + "@jest/fake-timers": "^28.1.2", + "@jest/globals": "^28.1.2", + "@jest/source-map": "^28.1.2", + "@jest/test-result": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-mock": "^28.1.1", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.1", + "jest-snapshot": "^28.1.2", + "jest-util": "^28.1.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "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 + }, + "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, - "optional": true, "requires": { - "is-buffer": "^1.1.5" + "has-flag": "^4.0.0" } } } }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "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, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "optional": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "jest-snapshot": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.2.tgz", + "integrity": "sha512-wzrieFttZYfLvrCVRJxX+jwML2YTArOUqFpCoSVy1QUapx+LlV9uLbV/mMEhYj4t7aMeE9aSQFHSvV/oNoDAMA==", "dev": true, - "optional": true, "requires": { - "kind-of": "^3.0.2" + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^28.1.1", + "@jest/transform": "^28.1.2", + "@jest/types": "^28.1.1", + "@types/babel__traverse": "^7.0.6", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^28.1.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^28.1.1", + "jest-get-type": "^28.0.2", + "jest-haste-map": "^28.1.1", + "jest-matcher-utils": "^28.1.1", + "jest-message-util": "^28.1.1", + "jest-util": "^28.1.1", + "natural-compare": "^1.4.0", + "pretty-format": "^28.1.1", + "semver": "^7.3.5" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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, - "optional": true, "requires": { - "is-buffer": "^1.1.5" + "has-flag": "^4.0.0" } } } }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "jest-util": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.1.tgz", + "integrity": "sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw==", "dev": true, - "optional": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "@jest/types": "^28.1.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "optional": true + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", + "dev": true + }, + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "optional": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "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==" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "jest-validate": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.1.tgz", + "integrity": "sha512-Kpf6gcClqFCIZ4ti5++XemYJWUPCFUW+N2gknn+KgnDf549iLul3cBuKVe1YcWRlaF8tZV8eJCap0eECOEE3Ug==", "dev": true, "requires": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" + "@jest/types": "^28.1.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^28.0.2", + "leven": "^3.1.0", + "pretty-format": "^28.1.1" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" - }, - "is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", - "dev": true - }, - "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 - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", - "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "jest-watcher": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.1.tgz", + "integrity": "sha512-RQIpeZ8EIJMxbQrXpJQYIIlubBnB9imEHsxxE41f54ZwcqWLysL/A0ZcdMirf+XsMn3xfphVQVV4EW0/p7i7Ug==", "dev": true, - "optional": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "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, - "optional": true - }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "@jest/test-result": "^28.1.1", + "@jest/types": "^28.1.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.1", + "string-length": "^4.0.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "jest-worker": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.1.tgz", + "integrity": "sha512-Au7slXB08C6h+xbJPp7VIb6U0XX5Kc9uel/WFc6/rcTzGiaVCBRngBExSYuXSLFPULPSYU3cJ3ybS988lNFQhQ==", "dev": true, - "optional": true + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, "jmespath": { "version": "0.15.0", @@ -4383,9 +15474,9 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -4397,18 +15488,18 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -4422,37 +15513,21 @@ "dev": true }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "requires": { - "minimist": "^1.2.5" - } - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz", + "integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==" }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "optional": true + "dev": true }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "requires": { - "package-json": "^6.3.0" - } + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true }, "leven": { "version": "3.1.0", @@ -4460,15 +15535,6 @@ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, - "levenary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", - "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", - "dev": true, - "requires": { - "leven": "^3.1.0" - } - }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4479,6 +15545,12 @@ "type-check": "~0.4.0" } }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -4498,6 +15570,12 @@ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4510,34 +15588,12 @@ "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", "dev": true }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, "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==", "requires": { "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } } }, "make-dir": { @@ -4561,23 +15617,21 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "optional": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, - "optional": true, "requires": { - "object-visit": "^1.0.0" + "tmpl": "1.0.5" } }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4585,136 +15639,39 @@ "dev": true }, "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, - "optional": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "optional": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } + "braces": "^3.0.1", + "picomatch": "^2.2.3" } }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true }, "minipass": { "version": "3.1.3", @@ -4733,29 +15690,6 @@ "yallist": "^4.0.0" } }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "optional": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "optional": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -4767,36 +15701,25 @@ "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==" }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } }, "nan": { "version": "2.15.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "optional": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4819,53 +15742,51 @@ } }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, - "node-properties-parser": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/node-properties-parser/-/node-properties-parser-0.0.2.tgz", - "integrity": "sha1-y4WjUFWW6+TANFNpGufV13uoTaA=" + "node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true }, "nodemon": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz", - "integrity": "sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==", + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", "dev": true, "requires": { - "chokidar": "^3.2.2", - "debug": "^3.2.6", + "chokidar": "^3.5.2", + "debug": "^3.2.7", "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.7", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", "supports-color": "^5.5.0", "touch": "^3.1.0", - "undefsafe": "^2.0.3", - "update-notifier": "^4.1.0" + "undefsafe": "^2.0.5" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true } } }, @@ -4896,11 +15817,14 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } }, "npmlog": { "version": "4.1.2", @@ -4923,70 +15847,28 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "optional": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "object-inspect": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "optional": true, - "requires": { - "isobject": "^3.0.0" - } + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, "object.getownpropertydescriptors": { @@ -4999,16 +15881,6 @@ "es-abstract": "^1.17.0-next.1" } }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "optional": true, - "requires": { - "isobject": "^3.0.1" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5017,6 +15889,15 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -5031,12 +15912,6 @@ "word-wrap": "^1.2.3" } }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true - }, "p-limit": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", @@ -5058,26 +15933,6 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5103,12 +15958,25 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "optional": true + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "requires": { + "parse5": "^6.0.1" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + } + } }, "path-exists": { "version": "4.0.0", @@ -5138,10 +16006,16 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "pify": { @@ -5151,15 +16025,15 @@ "dev": true }, "pino": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.13.1.tgz", - "integrity": "sha512-QQf67BU+cANnc/2U+wzUV20UjO5oBryWpnNyKshdLfT9BdeiXlh9wxLGmOjAuBWMYITdMs+BtJSQQNlGRNbWpA==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz", + "integrity": "sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==", "requires": { "fast-redact": "^3.0.0", "fast-safe-stringify": "^2.0.8", - "fastify-warning": "^0.2.0", "flatstr": "^1.0.12", "pino-std-serializers": "^3.1.0", + "process-warning": "^1.0.0", "quick-format-unescaped": "^4.0.3", "sonic-boom": "^1.0.2" } @@ -5228,13 +16102,10 @@ "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==" }, "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true }, "pkg-dir": { "version": "3.0.0", @@ -5286,47 +16157,71 @@ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==" }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "optional": true - }, "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 }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true + "pretty-format": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.1.tgz", + "integrity": "sha512-wwJbVTGFHeucr5Jw2bQ9P+VYHyLdAqedFLEkdQUVaBF/eiidDwH5OpilINq4mEfhbCjLnirt6HTTDhv1HaTIQw==", + "dev": true, + "requires": { + "@jest/schemas": "^28.0.2", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } }, "printj": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", - "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", + "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==" }, "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==" }, + "process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "properties-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/properties-parser/-/properties-parser-0.3.1.tgz", + "integrity": "sha1-ExbpU5/7/ZOEXjabIRAiq9R4dxo=", + "requires": { + "string.prototype.codepointat": "^0.2.0" + } + }, "pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -5348,15 +16243,6 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "pupa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", - "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", - "dev": true, - "requires": { - "escape-goat": "^2.0.0" - } - }, "quadtree-lib": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/quadtree-lib/-/quadtree-lib-1.0.9.tgz", @@ -5369,21 +16255,15 @@ "dev": true }, "quick-format-unescaped": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz", - "integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==" - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, "read-pkg": { "version": "4.0.1", @@ -5419,27 +16299,32 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" } }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true }, "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", "dev": true, "requires": { - "regenerate": "^1.4.0" + "regenerate": "^1.4.2" } }, "regenerator-runtime": { @@ -5449,24 +16334,12 @@ "dev": true }, "regenerator-transform": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz", - "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4", - "private": "^0.1.8" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", "dev": true, - "optional": true, "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "@babel/runtime": "^7.8.4" } }, "regexpp": { @@ -5476,47 +16349,29 @@ "dev": true }, "regexpu-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", - "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" - } - }, - "registry-auth-token": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", - "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", "dev": true, "requires": { - "rc": "^1.2.8" + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" } }, "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", "dev": true }, "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -5530,27 +16385,6 @@ } } }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true, - "optional": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "optional": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "optional": true - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5574,12 +16408,31 @@ "dev": true }, "resolve": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", - "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "requires": { - "path-parse": "^1.0.6" + "resolve-from": "^5.0.0" + }, + "dependencies": { + "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 + } } }, "resolve-from": { @@ -5588,28 +16441,11 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true, - "optional": true - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "optional": true + "resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true }, "reusify": { "version": "1.0.4", @@ -5640,11 +16476,11 @@ } }, "rxjs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.0.0.tgz", - "integrity": "sha512-I1V/ArAtGJg4kmCfms8fULm0SwYgEsAf2d5WPCBGzTYm2qTjO3Tx4EDFaGjbOox8CeEsC69jQK22mnmfyA26sw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz", + "integrity": "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==", "requires": { - "tslib": "~2.1.0" + "tslib": "^2.1.0" } }, "safe-buffer": { @@ -5652,15 +16488,10 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "optional": true, - "requires": { - "ret": "~0.1.10" - } + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "seek-bzip": { "version": "1.0.6", @@ -5676,51 +16507,27 @@ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, - "optional": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "kind-of": "^6.0.2" } }, "shebang-command": { @@ -5739,9 +16546,9 @@ "dev": true }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-concat": { "version": "1.0.1", @@ -5749,30 +16556,38 @@ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", "requires": { "decompress-response": "^4.2.0", "once": "^1.3.1", "simple-concat": "^1.0.0" + } + }, + "simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dev": true, + "requires": { + "semver": "~7.0.0" }, "dependencies": { - "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "requires": { - "mimic-response": "^2.0.0" - } - }, - "mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true } } }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -5790,130 +16605,6 @@ "is-fullwidth-code-point": "^3.0.0" } }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "optional": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "optional": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "sonic-boom": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", @@ -5928,36 +16619,15 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "optional": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true, - "optional": true - }, "spawn-command": { "version": "0.0.2-1", "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", @@ -5996,16 +16666,6 @@ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, "split2": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", @@ -6031,43 +16691,66 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "sqlite": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-4.1.2.tgz", + "integrity": "sha512-FlBG51gHbux5vPjwnoqFEghNGvnTMTbHyiI09U3qFTQs9AtWuwd4i++6+WCusCXKrVdIDLzfdGekrolr3m4U4A==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "dev": true, - "optional": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "escape-string-regexp": "^2.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true } } }, + "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==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, + "string.prototype.codepointat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", + "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" + }, "string.prototype.trimend": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -6077,25 +16760,18 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "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==", - "requires": { - "safe-buffer": "~5.1.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } }, "strip-bom": { @@ -6104,10 +16780,10 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, "supports-color": { @@ -6118,6 +16794,39 @@ "has-flag": "^3.0.0" } }, + "supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "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 + }, "table": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", @@ -6165,11 +16874,26 @@ "yallist": "^4.0.0" } }, - "term-size": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", - "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==", - "dev": true + "terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + } + }, + "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, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } }, "text-table": { "version": "0.2.0", @@ -6177,52 +16901,39 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "requires": { + "any-promise": "^1.0.0" + } }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "optional": true, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "thenify": ">= 3.1.0 < 4" } }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", "dev": true }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "optional": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true }, "to-regex-range": { "version": "5.0.1", @@ -6242,6 +16953,11 @@ "nopt": "~1.0.10" } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, "tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -6249,35 +16965,38 @@ "dev": true }, "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, - "requires": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.5.0.tgz", + "integrity": "sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", + "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" }, "dependencies": { - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true } } }, "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", "dev": true, "requires": { "@types/json5": "^0.0.29", @@ -6304,9 +17023,9 @@ } }, "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, "tsutils": { "version": "3.21.0", @@ -6334,226 +17053,185 @@ "prelude-ls": "^1.2.1" } }, - "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 - }, - "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, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typescript": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", - "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", - "dev": true - }, - "undefsafe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", - "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", - "dev": true, - "requires": { - "debug": "^2.2.0" - } - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, - "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "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 }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "optional": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "requires": { - "crypto-random-string": "^2.0.0" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "optional": true, + "typeorm": { + "version": "0.2.45", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.2.45.tgz", + "integrity": "sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA==", "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "@sqltools/formatter": "^1.2.2", + "app-root-path": "^3.0.0", + "buffer": "^6.0.3", + "chalk": "^4.1.0", + "cli-highlight": "^2.1.11", + "debug": "^4.3.1", + "dotenv": "^8.2.0", + "glob": "^7.1.6", + "js-yaml": "^4.0.0", + "mkdirp": "^1.0.4", + "reflect-metadata": "^0.1.13", + "sha.js": "^2.4.11", + "tslib": "^2.1.0", + "uuid": "^8.3.2", + "xml2js": "^0.4.23", + "yargs": "^17.0.1", + "zen-observable-ts": "^1.0.0" }, "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "optional": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "optional": true, - "requires": { - "isarray": "1.0.0" - } - } - } + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "optional": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "optional": true - }, - "update-notifier": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", - "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", - "dev": true, - "requires": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "dependencies": { "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, + "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==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "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 + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } }, "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, "requires": { "has-flag": "^4.0.0" } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "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==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs": { + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "requires": { + "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" + } + }, + "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==" } } }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==" + }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "requires": { - "punycode": "^2.1.0" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true, - "optional": true + "unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { - "prepend-http": "^2.0.0" + "punycode": "^2.1.0" } }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "optional": true - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v8-compile-cache": { "version": "2.3.0", @@ -6561,6 +17239,23 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "v8-compile-cache-lib": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", + "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", + "dev": true + }, + "v8-to-istanbul": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", + "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + } + }, "v8flags": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", @@ -6580,6 +17275,29 @@ "spdx-expression-parse": "^3.0.0" } }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6631,15 +17349,6 @@ } } }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" - } - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -6661,23 +17370,19 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "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, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" } }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, "y18n": { "version": "4.0.1", @@ -6690,9 +17395,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "requires": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -6704,7 +17409,7 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" + "yargs-parser": "^18.1.2" } }, "yargs-parser": { @@ -6721,6 +17426,20 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "zen-observable-ts": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", + "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", + "requires": { + "@types/zen-observable": "0.8.3", + "zen-observable": "0.8.15" + } } } } diff --git a/package.json b/package.json index 1d62124b8..c064d38e8 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,28 @@ { "name": "@runejs/server", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.2", "description": "A RuneScape game server emulator written in TypeScript.", "main": "dist/index.js", "scripts": { "start": "npm run build && concurrently \"npm run build:watch\" \"npm run start:infra\" \"npm run start:game\"", - "start:game": "nodemon --delay 5000ms --max-old-space-size=2048 dist/main.js", + "start:game": "nodemon --delay 5000ms --max-old-space-size=2048 dist/server/runner.js -- -game", "start:game:dev": "npm run build && concurrently \"npm run build:watch\" \"npm run start:game\"", - "start:login": "node --max-old-space-size=1024 dist/game-engine/login-server.js", - "start:update": "node --max-old-space-size=1024 dist/game-engine/update-server.js", + "start:login": "node --max-old-space-size=1024 dist/server/runner.js -- -login", + "start:update": "node --max-old-space-size=1024 dist/server/runner.js -- -update", "start:infra": "concurrently \"npm run start:update\" \"npm run start:login\"", "start:standalone": "concurrently \"npm run start:infra\" \"npm run start:game\"", + "game": "npm run start:game", + "game:dev": "npm run start:game:dev", + "login": "npm run start:login", + "update": "npm run start:update", + "infra": "npm run start:infra", + "standalone": "npm run start:standalone", "lint": "eslint --ext .ts src", "lint:fix": "eslint --ext .ts src --fix", "build:watch": "babel ./src --out-dir dist --extensions \".ts,.tsx,.js\" --source-maps --watch", - "build": "rimraf dist && babel ./src --out-dir dist --extensions \".ts,.tsx,.js\" --source-maps" + "build": "rimraf dist && babel ./src --out-dir dist --extensions \".ts,.tsx,.js\" --source-maps", + "test": "jest", + "typecheck": "tsc -p ./ --noEmit" }, "repository": { "type": "git", @@ -34,47 +42,49 @@ }, "homepage": "https://github.com/runejs/server#readme", "dependencies": { - "@runejs/core": "^1.5.4", - "@runejs/filestore": "^0.15.2", - "@runejs/login-server": "^1.2.2", - "@runejs/update-server": "^1.2.2", + "@runejs/common": "^2.0.1", + "@runejs/store": "^1.0.0-beta.1", + "@runejs/login-server": "^2.0.0", + "@runejs/update-server": "^1.3.0", "bigi": "^1.4.2", - "js-yaml": "^3.13.1", - "json5": "^2.1.3", + "js-yaml": "^3.14.1", + "json5": "^2.2.2", "lodash": "^4.17.21", "quadtree-lib": "^1.0.9", - "rxjs": "^7.0.0", + "rxjs": "^7.5.4", "source-map-support": "^0.5.19", - "tslib": "^2.1.0", - "uuid": "^3.3.3", - "yargs": "^15.3.1" + "tslib": "^2.3.1", + "uuid": "^3.4.0", + "yargs": "^15.4.1" }, "devDependencies": { - "@babel/cli": "^7.14.5", - "@babel/core": "^7.10.2", - "@babel/node": "^7.12.1", - "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/preset-env": "^7.10.2", - "@babel/preset-typescript": "^7.10.1", + "@babel/cli": "^7.17.6", + "@babel/core": "^7.17.5", + "@babel/node": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/preset-env": "^7.16.11", + "@babel/preset-typescript": "^7.16.7", "@runejs/eslint-config": "^1.0.0", - "@types/js-yaml": "^3.12.1", + "@types/jest": "^28.1.4", + "@types/js-yaml": "^3.12.7", "@types/json5": "0.0.30", - "@types/lodash": "^4.14.149", - "@types/node": "^14.14.37", - "@types/uuid": "^3.4.6", - "@types/yargs": "^13.0.4", - "@typescript-eslint/eslint-plugin": "^4.29.3", - "@typescript-eslint/parser": "^4.29.3", - "babel-plugin-module-resolver": "^4.0.0", - "chokidar": "^3.4.3", - "concurrently": "^5.1.0", + "@types/lodash": "^4.14.179", + "@types/node": "^16.11.26", + "@types/uuid": "^3.4.10", + "@types/yargs": "^15.0.14", + "@typescript-eslint/eslint-plugin": "^4.33.0", + "@typescript-eslint/parser": "^4.33.0", + "babel-plugin-module-resolver": "^4.1.0", + "chokidar": "^3.5.3", + "concurrently": "^5.3.0", "eslint": "^7.32.0", + "jest": "^28.1.2", "mkdirp": "^1.0.4", - "nodemon": "^2.0.6", + "nodemon": "^2.0.20", "rimraf": "^3.0.2", - "ts-node": "^9.1.1", - "tsconfig-paths": "^3.9.0", - "typescript": "^4.2.3" + "ts-node": "^10.5.0", + "tsconfig-paths": "^3.12.0", + "typescript": "^4.5.5" }, "eslintConfig": { "extends": [ diff --git a/src/game-engine/world/action/index.ts b/src/engine/action/action-pipeline.ts similarity index 78% rename from src/game-engine/world/action/index.ts rename to src/engine/action/action-pipeline.ts index 47d747e2d..502f90fae 100644 --- a/src/game-engine/world/action/index.ts +++ b/src/engine/action/action-pipeline.ts @@ -1,13 +1,12 @@ -import { gameEngineDist } from '@engine/util/directories'; -import { getFiles } from '@engine/util/files'; -import { logger } from '@runejs/core'; -import { Actor } from '@engine/world/actor/actor'; -import { ActionHook, TaskExecutor } from '@engine/world/action/hooks'; -import { Position } from '@engine/world/position'; -import { Player } from '@engine/world/actor/player/player'; import { Subscription } from 'rxjs'; + +import { logger } from '@runejs/common'; import { LandscapeObject } from '@runejs/filestore'; +import { Actor, Player } from '@engine/world/actor'; +import { ActionHook, TaskExecutor } from '@engine/action'; +import { Position } from '@engine/world'; + /** * The priority of an queueable action within the pipeline. @@ -32,6 +31,7 @@ export type ActionType = | 'item_on_npc' | 'item_on_player' | 'item_on_item' + | 'item_on_world_item' | 'item_swap' | 'move_item' | 'spawned_item_interaction' @@ -44,7 +44,8 @@ export type ActionType = | 'player_command' | 'player_interaction' | 'region_change' - | 'equipment_change'; + | 'equipment_change' + | 'prayer'; export const gentleActions: ActionType[] = [ @@ -106,8 +107,8 @@ export class ActionPipeline { .subscribe(async () => this.cancelRunningTasks()); } - public static getPipe(action: ActionType): ActionPipeHandler { - return ActionPipeline.pipes.get(action); + public static getPipe(action: ActionType): ActionPipeHandler | null { + return ActionPipeline.pipes.get(action) || null; } public static register(action: ActionType, actionPipeHandlerFn: ActionPipeHandler): void { @@ -223,39 +224,3 @@ export class ActionPipeline { } } - - -/** - * Finds and loads all available action pipe files (`*.action.ts`). - */ -export async function loadActionFiles(): Promise { - const ACTION_DIRECTORY = `${gameEngineDist}/world/action`; - const blacklist = []; - const loadedActions: string[] = []; - - for await(const path of getFiles(ACTION_DIRECTORY, blacklist)) { - if(!path.endsWith('.action.ts') && !path.endsWith('.action.js')) { - continue; - } - - const location = '.' + path.substring(ACTION_DIRECTORY.length).replace('.js', ''); - - try { - const importedAction = (require(location)?.default || null) as ActionPipe | null; - if(importedAction && Array.isArray(importedAction) && importedAction[0] && importedAction[1]) { - ActionPipeline.register(importedAction[0], importedAction[1]); - loadedActions.push(importedAction[0]); - } - } catch(error) { - logger.error(`Error loading action file at ${location}:`); - logger.error(error); - } - } - - logger.info(`Loaded action pipes: ${loadedActions.join(', ')}.`); - - return Promise.resolve(); -} - - -export * from './hooks/index'; diff --git a/src/game-engine/world/action/hooks/index.ts b/src/engine/action/hook/action-hook.ts similarity index 85% rename from src/game-engine/world/action/hooks/index.ts rename to src/engine/action/hook/action-hook.ts index 4154bed53..eb9989500 100644 --- a/src/game-engine/world/action/hooks/index.ts +++ b/src/engine/action/hook/action-hook.ts @@ -1,7 +1,6 @@ -import { actionHookMap } from '@engine/game-server'; -import { QuestKey } from '@engine/config/quest-config'; -import { ActionStrength, ActionType } from '@engine/world/action'; -import { HookTask } from '@engine/world/action/hooks/task'; +import { QuestKey } from '@engine/config'; +import { ActionStrength, ActionType, HookTask } from '@engine/action'; +import { actionHookMap } from '@engine/plugins'; /** @@ -58,7 +57,3 @@ export const getActionHooks = (actionType: ActionType, fil export function sortActionHooks(actionHooks: ActionHook[]): ActionHook[] { return actionHooks.sort(actionHook => actionHook.questRequirement !== undefined ? -1 : 1); } - - -export * from './hook-filters'; -export * from './task'; diff --git a/src/engine/action/hook/hook-filters.test.ts b/src/engine/action/hook/hook-filters.test.ts new file mode 100644 index 000000000..54cae37c0 --- /dev/null +++ b/src/engine/action/hook/hook-filters.test.ts @@ -0,0 +1,30 @@ +import { advancedNumberHookFilter } from './hook-filters' + +describe('action/hook hook filters', () => { + describe('advancedNumberHookFilter', () => { + + describe('when expected is a number array', () => { + const expected = [ 1, 2, 3 ] + + describe('when input is in the array', () => { + const input = 2 + + test('should return true', () => { + const result = advancedNumberHookFilter(expected, input) + + expect(result).toEqual(true) + }) + }) + + describe('when input is not in the array', () => { + const input = 999 + + test('should return false', () => { + const result = advancedNumberHookFilter(expected, input) + + expect(result).toEqual(false) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/src/game-engine/world/action/hooks/hook-filters.ts b/src/engine/action/hook/hook-filters.ts similarity index 95% rename from src/game-engine/world/action/hooks/hook-filters.ts rename to src/engine/action/hook/hook-filters.ts index 0a8bee8f9..ff558cbe4 100644 --- a/src/game-engine/world/action/hooks/hook-filters.ts +++ b/src/engine/action/hook/hook-filters.ts @@ -1,5 +1,5 @@ -import { Player } from '@engine/world/actor/player/player'; -import { ActionHook } from '@engine/world/action/hooks/index'; +import { ActionHook } from '@engine/action'; +import { Player } from '@engine/world/actor'; export const stringHookFilter = (expected: string | string[], input: string): boolean => { diff --git a/src/engine/action/hook/index.ts b/src/engine/action/hook/index.ts new file mode 100644 index 000000000..c1f2c0bd7 --- /dev/null +++ b/src/engine/action/hook/index.ts @@ -0,0 +1,3 @@ +export * from './hook-filters'; +export * from './task'; +export * from './action-hook'; diff --git a/src/game-engine/world/action/hooks/task.ts b/src/engine/action/hook/task.ts similarity index 85% rename from src/game-engine/world/action/hooks/task.ts rename to src/engine/action/hook/task.ts index 1d637792d..938fa79e5 100644 --- a/src/game-engine/world/action/hooks/task.ts +++ b/src/engine/action/hook/task.ts @@ -1,17 +1,25 @@ import uuidv4 from 'uuid/v4'; import { lastValueFrom, Subscription, timer } from 'rxjs'; -import { Actor } from '@engine/world/actor/actor'; -import { ActionHook } from '@engine/world/action'; + +import { logger } from '@runejs/common'; + +import { ActionHook, ActionStrength } from '@engine/action'; import { World } from '@engine/world'; -import { logger } from '@runejs/core'; -import { Player } from '@engine/world/actor/player/player'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { ActionStrength } from '@engine/world/action'; +import { Actor, Player, Npc } from '@engine/world/actor'; export type TaskSessionData = { [key: string]: any }; +export interface TaskDetails { + actor: Actor; + player: Player | undefined; + npc: Npc | undefined; + actionData: T; + session: TaskSessionData; +} + + export interface HookTask { canActivate?: (task: TaskExecutor, iteration?: number) => boolean | Promise; activate: (task: TaskExecutor, iteration?: number) => void | undefined | boolean | Promise; @@ -44,15 +52,17 @@ export class TaskExecutor { public async run(): Promise { this.running = true; + /* eslint-disable @typescript-eslint/no-non-null-assertion */ if(!!this.task.delay || !!this.task.delayMs) { await lastValueFrom(timer(this.task.delayMs !== undefined ? this.task.delayMs : - (this.task.delay * World.TICK_LENGTH))); + (this.task.delay! * World.TICK_LENGTH))); } if(!!this.task.interval || !!this.task.intervalMs) { // Looping execution task const intervalMs = this.task.intervalMs !== undefined ? this.task.intervalMs : - (this.task.interval * World.TICK_LENGTH); + (this.task.interval! * World.TICK_LENGTH); + /* eslint-enable @typescript-eslint/no-non-null-assertion */ await new Promise(resolve => { this.intervalSubscription = timer(0, intervalMs).subscribe( @@ -134,27 +144,13 @@ export class TaskExecutor { if(this.task?.onComplete) { await this.task.onComplete(this, this.iteration); } - - this.session = null; } - public getDetails(): { - actor: Actor; - player: Player | undefined; - npc: Npc | undefined; - actionData: T; - session: TaskSessionData; } { - const { - type: { - player, - npc - } - } = this.actor; - + public getDetails(): TaskDetails { return { actor: this.actor, - player, - npc, + player: this.actor.isPlayer ? this.actor as Player : undefined, + npc: this.actor.isNpc ? this.actor as Npc : undefined, actionData: this.actionData, session: this.session }; diff --git a/src/engine/action/index.ts b/src/engine/action/index.ts new file mode 100644 index 000000000..ab0fabe8b --- /dev/null +++ b/src/engine/action/index.ts @@ -0,0 +1,4 @@ +export * from './action-pipeline'; +export * from './hook'; +export * from './pipe'; +export * from './loader'; diff --git a/src/engine/action/loader.ts b/src/engine/action/loader.ts new file mode 100644 index 000000000..4799073e8 --- /dev/null +++ b/src/engine/action/loader.ts @@ -0,0 +1,40 @@ +import { logger } from '@runejs/common'; + +import { ActionPipe, ActionPipeline } from '@engine/action'; +import { getFiles } from '@engine/util'; +import { BUILD_DIR } from '@engine/config'; +import { join } from 'path'; + + +/** + * Finds and loads all available action pipe files (`*.action.ts`). + */ +export async function loadActionFiles(): Promise { + const ACTION_DIRECTORY = join(BUILD_DIR, 'action'); + const PIPE_DIRECTORY = join(ACTION_DIRECTORY, 'pipe'); + const blacklist = []; + const loadedActions: string[] = []; + + for await(const path of getFiles(PIPE_DIRECTORY, blacklist)) { + if(!path.endsWith('.action.ts') && !path.endsWith('.action.js')) { + continue; + } + + const location = '.' + path.substring(ACTION_DIRECTORY.length).replace('.js', ''); + + try { + const importedAction = (require(location)?.default || null) as ActionPipe | null; + if(importedAction && Array.isArray(importedAction) && importedAction[0] && importedAction[1]) { + ActionPipeline.register(importedAction[0], importedAction[1]); + loadedActions.push(importedAction[0]); + } + } catch(error) { + logger.error(`Error loading action file at ${location}:`); + logger.error(error); + } + } + + logger.info(`Loaded action pipes: ${loadedActions.join(', ')}.`); + + return Promise.resolve(); +} diff --git a/src/game-engine/world/action/button.action.ts b/src/engine/action/pipe/button.action.ts similarity index 80% rename from src/game-engine/world/action/button.action.ts rename to src/engine/action/pipe/button.action.ts index 82e0235e9..35184eb4b 100644 --- a/src/game-engine/world/action/button.action.ts +++ b/src/engine/action/pipe/button.action.ts @@ -1,7 +1,7 @@ -import { Player } from '@engine/world/actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { advancedNumberHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { + ActionHook, getActionHooks, advancedNumberHookFilter, questHookFilter, ActionPipe, RunnableHooks +} from '@engine/action'; /** @@ -44,7 +44,7 @@ export interface ButtonAction { * @param widgetId * @param buttonId */ -const buttonActionPipe = (player: Player, widgetId: number, buttonId: number): RunnableHooks => { +const buttonActionPipe = (player: Player, widgetId: number, buttonId: number): RunnableHooks | null => { let matchingHooks = getActionHooks('button') .filter(plugin => questHookFilter(player, plugin) && ( @@ -61,12 +61,6 @@ const buttonActionPipe = (player: Player, widgetId: number, buttonId: number): R matchingHooks = questActions; } - if(player.metadata.buttonListener) { - if(widgetId === player.metadata.buttonListener.widgetId) { - player.metadata.buttonListener.event.next(buttonId); - } - } - if(matchingHooks.length === 0) { player.outgoingPackets.chatboxMessage(`Unhandled button interaction: ${widgetId}:${buttonId}`); return null; diff --git a/src/game-engine/world/action/equipment-change.action.ts b/src/engine/action/pipe/equipment-change.action.ts similarity index 81% rename from src/game-engine/world/action/equipment-change.action.ts rename to src/engine/action/pipe/equipment-change.action.ts index e3123fb86..c38a70ed3 100644 --- a/src/game-engine/world/action/equipment-change.action.ts +++ b/src/engine/action/pipe/equipment-change.action.ts @@ -1,9 +1,9 @@ -import { Player } from '@engine/world/actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { findItem } from '@engine/config'; -import { EquipmentSlot, ItemDetails } from '@engine/config/item-config'; -import { numberHookFilter, stringHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { findItem, EquipmentSlot, ItemDetails } from '@engine/config'; +import { + ActionHook, getActionHooks, numberHookFilter, stringHookFilter, questHookFilter, ActionPipe, RunnableHooks +} from '@engine/action'; +import { logger } from '@runejs/common'; /** @@ -54,7 +54,7 @@ export interface EquipmentChangeAction { * @param slot */ const equipmentChangeActionPipe = (player: Player, itemId: number, - eventType: EquipmentChangeType, slot: EquipmentSlot): RunnableHooks => { + eventType: EquipmentChangeType, slot: EquipmentSlot): RunnableHooks | null => { let matchingHooks = getActionHooks('equipment_change', equipActionHook => { if(!questHookFilter(player, equipActionHook)) { return false; @@ -85,12 +85,19 @@ const equipmentChangeActionPipe = (player: Player, itemId: number, return null; } + const itemDetails = findItem(itemId); + + if(!itemDetails) { + logger.error(`Item ${itemId} not registered on the server [equipment-change action pipe]`); + return null; + } + return { hooks: matchingHooks, action: { player, itemId, - itemDetails: findItem(itemId), + itemDetails, eventType, equipmentSlot: slot } diff --git a/src/engine/action/pipe/index.ts b/src/engine/action/pipe/index.ts new file mode 100644 index 000000000..b43ed0a87 --- /dev/null +++ b/src/engine/action/pipe/index.ts @@ -0,0 +1,21 @@ +export * from './button.action'; +export * from './equipment-change.action'; +export * from './item-interaction.action'; +export * from './item-on-item.action'; +export * from './item-on-world-item.action'; +export * from './item-on-npc.action'; +export * from './item-on-object.action'; +export * from './item-on-player.action'; +export * from './item-swap.action'; +export * from './magic-on-npc.action'; +export * from './move-item.action'; +export * from './npc-init.action'; +export * from './npc-interaction.action'; +export * from './object-interaction.action'; +export * from './player-command.action'; +export * from './player-init.action'; +export * from './player-interaction.action'; +export * from './prayer.action'; +export * from './region-change.action'; +export * from './spawned-item-interaction.action'; +export * from './widget-interaction.action'; diff --git a/src/game-engine/world/action/item-interaction.action.ts b/src/engine/action/pipe/item-interaction.action.ts similarity index 87% rename from src/game-engine/world/action/item-interaction.action.ts rename to src/engine/action/pipe/item-interaction.action.ts index 964e5ea52..87ab456cc 100644 --- a/src/game-engine/world/action/item-interaction.action.ts +++ b/src/engine/action/pipe/item-interaction.action.ts @@ -1,9 +1,9 @@ -import { Player } from '@engine/world/actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { ItemDetails } from '@engine/config/item-config'; -import { findItem } from '@engine/config'; -import { numberHookFilter, stringHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { findItem, ItemDetails } from '@engine/config'; +import { + ActionHook, getActionHooks, numberHookFilter, stringHookFilter, questHookFilter, ActionPipe, RunnableHooks +} from '@engine/action'; +import { logger } from '@runejs/common'; /** @@ -58,7 +58,7 @@ export interface ItemInteractionAction { * @param option */ const itemInteractionActionPipe = (player: Player, itemId: number, slot: number, widgetId: number, - containerId: number, option: string): RunnableHooks => { + containerId: number, option: string): RunnableHooks | null => { const playerWidget = Object.values(player.interfaceState.widgetSlots).find((widget) => widget && widget.widgetId === widgetId); if(playerWidget && playerWidget.fakeWidget != undefined) { @@ -117,6 +117,13 @@ const itemInteractionActionPipe = (player: Player, itemId: number, slot: number, return null; } + const itemDetails = findItem(itemId); + + if(!itemDetails) { + logger.error(`Item ${itemId} not registered on the server [item-interaction action pipe]`); + return null; + } + return { hooks: matchingHooks, action: { @@ -125,7 +132,7 @@ const itemInteractionActionPipe = (player: Player, itemId: number, slot: number, itemSlot: slot, widgetId, containerId, - itemDetails: findItem(itemId), + itemDetails, option } } diff --git a/src/game-engine/world/action/item-on-item.action.ts b/src/engine/action/pipe/item-on-item.action.ts similarity index 74% rename from src/game-engine/world/action/item-on-item.action.ts rename to src/engine/action/pipe/item-on-item.action.ts index f91515bce..f3c50ccdc 100644 --- a/src/game-engine/world/action/item-on-item.action.ts +++ b/src/engine/action/pipe/item-on-item.action.ts @@ -1,8 +1,6 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Item } from '@engine/world/items/item'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { Item } from '@engine/world'; +import { ActionHook, getActionHooks, questHookFilter, ActionPipe, RunnableHooks } from '@engine/action'; /** @@ -52,17 +50,25 @@ export interface ItemOnItemAction { * @param usedWithWidgetId */ const itemOnItemActionPipe = (player: Player, usedItem: Item, usedSlot: number, usedWidgetId: number, - usedWithItem: Item, usedWithSlot: number, usedWithWidgetId: number): RunnableHooks => { + usedWithItem: Item, usedWithSlot: number, usedWithWidgetId: number): RunnableHooks | null => { if(player.busy) { - return; + return null; } // Find all item on item action plugins that match this action - let matchingHooks = getActionHooks('item_on_item').filter(plugin => - questHookFilter(player, plugin) && - (plugin.items.findIndex(i => i.item1 === usedItem.itemId && i.item2 === usedWithItem.itemId) !== -1 || - plugin.items.findIndex(i => i.item2 === usedItem.itemId && i.item1 === usedWithItem.itemId) !== -1 || - plugin.items.findIndex(i => i.item1 === usedItem.itemId && !i.item2 || i.item1 === usedWithItem.itemId && !i.item2 ) !== -1)); + let matchingHooks = getActionHooks('item_on_item', plugin => { + if(questHookFilter(player, plugin)) { + const used = usedItem.itemId; + const usedWith = usedWithItem.itemId; + + return (plugin.items.some(({ item1, item2 }) => { + const items = [ item1, item2 ]; + return items.includes(used) && items.includes(usedWith); + })); + } + + return false; + }); const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); diff --git a/src/game-engine/world/action/item-on-npc.action.ts b/src/engine/action/pipe/item-on-npc.action.ts similarity index 85% rename from src/game-engine/world/action/item-on-npc.action.ts rename to src/engine/action/pipe/item-on-npc.action.ts index e9eafd6ed..7f58fdbc1 100644 --- a/src/game-engine/world/action/item-on-npc.action.ts +++ b/src/engine/action/pipe/item-on-npc.action.ts @@ -1,10 +1,8 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Position } from '@engine/world/position'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { Item } from '@engine/world/items/item'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { advancedNumberHookFilter, questHookFilter, stringHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player, Npc } from '@engine/world/actor'; +import { Position, Item } from '@engine/world'; +import { + ActionHook, getActionHooks, advancedNumberHookFilter, questHookFilter, stringHookFilter, ActionPipe, RunnableHooks +} from '@engine/action'; /** @@ -55,7 +53,7 @@ export interface ItemOnNpcAction { * @param itemContainerId */ const itemOnNpcActionPipe = (player: Player, npc: Npc, position: Position, item: Item, - itemWidgetId: number, itemContainerId: number): RunnableHooks => { + itemWidgetId: number, itemContainerId: number): RunnableHooks | null => { const morphedNpc = player.getMorphedNpcDetails(npc); // Find all item on npc action plugins that reference this npc and item diff --git a/src/game-engine/world/action/item-on-object.action.ts b/src/engine/action/pipe/item-on-object.action.ts similarity index 86% rename from src/game-engine/world/action/item-on-object.action.ts rename to src/engine/action/pipe/item-on-object.action.ts index 9b5c2cf71..0a998d8cd 100644 --- a/src/game-engine/world/action/item-on-object.action.ts +++ b/src/engine/action/pipe/item-on-object.action.ts @@ -1,11 +1,9 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Position } from '@engine/world/position'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { Item } from '@engine/world/items/item'; -import { advancedNumberHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; import { LandscapeObject, ObjectConfig } from '@runejs/filestore'; -import { playerWalkTo } from '@engine/game-server'; +import { Position, Item } from '@engine/world'; +import { Player } from '@engine/world/actor'; +import { + ActionHook, getActionHooks, advancedNumberHookFilter, questHookFilter, ActionPipe, RunnableHooks +} from '@engine/action'; /** @@ -64,7 +62,7 @@ export interface ItemOnObjectAction { const itemOnObjectActionPipe = (player: Player, landscapeObject: LandscapeObject, objectConfig: ObjectConfig, position: Position, item: Item, itemWidgetId: number, itemContainerId: number, - cacheOriginal: boolean): RunnableHooks => { + cacheOriginal: boolean): RunnableHooks | null => { // Find all item on object action plugins that reference this location object let matchingHooks = getActionHooks('item_on_object') .filter(plugin => questHookFilter(player, plugin) && diff --git a/src/game-engine/world/action/item-on-player.action.ts b/src/engine/action/pipe/item-on-player.action.ts similarity index 88% rename from src/game-engine/world/action/item-on-player.action.ts rename to src/engine/action/pipe/item-on-player.action.ts index 551274826..28e517ac5 100644 --- a/src/game-engine/world/action/item-on-player.action.ts +++ b/src/engine/action/pipe/item-on-player.action.ts @@ -1,11 +1,9 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Position } from '@engine/world/position'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { logger } from '@runejs/core'; -import { Item } from '@engine/world/items/item'; -import { playerWalkTo } from '@engine/game-server'; -import { advancedNumberHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe } from '@engine/world/action/index'; +import { logger } from '@runejs/common'; + +import { Player } from '@engine/world/actor'; +import { Position, Item } from '@engine/world'; +import { ActionHook, getActionHooks, advancedNumberHookFilter, questHookFilter, ActionPipe } from '@engine/action'; +import { playerWalkTo } from '@engine/plugins'; /** diff --git a/src/engine/action/pipe/item-on-world-item.action.ts b/src/engine/action/pipe/item-on-world-item.action.ts new file mode 100644 index 000000000..3ae54c1d5 --- /dev/null +++ b/src/engine/action/pipe/item-on-world-item.action.ts @@ -0,0 +1,123 @@ +import { Player } from '@engine/world/actor'; +import { Item, WorldItem } from '@engine/world'; +import { ActionHook, getActionHooks, questHookFilter, ActionPipe, RunnableHooks } from '@engine/action'; + + +/** + * Defines an item-on-world-item action hook. + * + * @author jameskmonger + */ +export interface ItemOnWorldItemActionHook extends ActionHook { + /** + * The item pairs being used. Both items are optional so that you can specify a single item, a pair of items, or neither. + */ + items: { item?: number, worldItem?: number }[]; +} + + +/** + * The item-on-world-item action hook handler function to be called when the hook's conditions are met. + */ +export type itemOnWorldItemActionHandler = (itemOnWorldItemAction: ItemOnWorldItemAction) => void; + + +/** + * Details about an item-on-world-item action being performed. + * + * @author jameskmonger + */ +export interface ItemOnWorldItemAction { + /** + * The player performing the action. + */ + player: Player; + + /** + * The item being used. + */ + usedItem: Item; + + /** + * The WorldItem that the first item is being used on. + */ + usedWithItem: WorldItem; + + /** + * The ID of the UI widget that the item being used is in. + */ + usedWidgetId: number; + + /** + * The ID of the container that the item being used is in. + */ + usedContainerId: number; + + /** + * The slot within the container that the item being used is in. + */ + usedSlot: number; +} + +/** + * The pipe that the game engine hands item-on-world-item actions off to. + * + * This will call the `item_on_world_item` action hooks, if any are registered and match the action being performed. + * + * Both `item` and `worldItem` are optional, but if they are provided then they must match the items in use. + * + * @author jameskmonger + */ +const itemOnWorldItemActionPipe = ( + player: Player, + usedItem: Item, usedWithItem: WorldItem, + usedWidgetId: number, usedContainerId: number, usedSlot: number +): RunnableHooks | null => { + if(player.busy) { + return null; + } + + // Find all item on item action plugins that match this action + let matchingHooks = getActionHooks('item_on_world_item', plugin => { + if(questHookFilter(player, plugin)) { + const used = usedItem.itemId; + const usedWith = usedWithItem.itemId; + + return (plugin.items.some(({ item, worldItem }) => { + const itemMatch = item === undefined || item === used; + const worldItemMatch = worldItem === undefined || worldItem === usedWith; + + return itemMatch && worldItemMatch; + })); + } + + return false; + }); + + const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); + + if(questActions.length !== 0) { + matchingHooks = questActions; + } + + if(matchingHooks.length === 0) { + player.outgoingPackets.chatboxMessage( + `Unhandled item on world item interaction: ${usedItem.itemId} on ${usedWithItem.itemId}`); + return null; + } + + return { + hooks: matchingHooks, + action: { + player, + usedItem, usedWithItem, + usedWidgetId, usedContainerId, usedSlot + } + } +}; + + +/** + * Item-on-world-item action pipe definition. + */ +export default [ 'item_on_world_item', itemOnWorldItemActionPipe ] as ActionPipe; diff --git a/src/game-engine/world/action/item-swap.action.ts b/src/engine/action/pipe/item-swap.action.ts similarity index 78% rename from src/game-engine/world/action/item-swap.action.ts rename to src/engine/action/pipe/item-swap.action.ts index 680b1212b..5384c9d87 100644 --- a/src/game-engine/world/action/item-swap.action.ts +++ b/src/engine/action/pipe/item-swap.action.ts @@ -1,7 +1,5 @@ -import { Player } from '../actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { numberHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { ActionHook, getActionHooks, numberHookFilter, ActionPipe, RunnableHooks } from '@engine/action'; /** @@ -44,9 +42,13 @@ export interface ItemSwapAction { * @param widget */ const itemSwapActionPipe = (player: Player, fromSlot: number, toSlot: number, - widget: { widgetId: number, containerId: number }): RunnableHooks => { + widget: { widgetId: number, containerId: number }): RunnableHooks | null => { const matchingHooks = getActionHooks('item_swap') - .filter(plugin => numberHookFilter(plugin.widgetId || plugin.widgetIds, widget.widgetId)); + .filter(plugin => ( + (plugin.widgetId || plugin.widgetIds) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + && numberHookFilter((plugin.widgetId || plugin.widgetIds)!, widget.widgetId) + )); if(!matchingHooks || matchingHooks.length === 0) { player.sendMessage(`Unhandled Swap Items action: widget[${widget.widgetId}] container[${widget.containerId}] fromSlot[${fromSlot} toSlot${toSlot}`); diff --git a/src/game-engine/world/action/magic-on-npc.action.ts b/src/engine/action/pipe/magic-on-npc.action.ts similarity index 82% rename from src/game-engine/world/action/magic-on-npc.action.ts rename to src/engine/action/pipe/magic-on-npc.action.ts index 34c02e5e6..af2b1723b 100644 --- a/src/game-engine/world/action/magic-on-npc.action.ts +++ b/src/engine/action/pipe/magic-on-npc.action.ts @@ -1,75 +1,72 @@ -import { Player } from '@engine/world/actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { advancedNumberHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; -import { Npc } from '../actor/npc/npc'; - - -/** - * Defines a button action hook. - */ -export interface MagicOnNPCActionHook extends ActionHook { - // The npc world id that was clicked on after choosing the spell - npcworldId?: number; - // The IDs of the UI widgets that the buttons are on. - widgetIds?: number[]; - // The child ID or list of child IDs of the button(s) within the UI widget. - buttonIds?: number | number[]; - // Whether or not this item action should cancel other running or queued actions. - cancelActions?: boolean; -} - - -/** - * The button action hook handler function to be called when the hook's conditions are met. - */ -export type magiconnpcActionHandler = (buttonAction: MagicOnNPCAction) => void | Promise; - - -/** - * Details about a button action being performed. - */ -export interface MagicOnNPCAction { - // The npc world id that was clicked on after choosing the spell - npc: Npc; - // The player performing the action. - player: Player; - // The ID of the UI widget that the button is on. - widgetId: number; - // The child ID of the button within the UI widget. - buttonId: number; -} - - -/** - * The pipe that the game engine hands button actions off to. - * @param npc - * @param player - * @param widgetId - * @param buttonId - */ -const magicOnNpcActionPipe = (npc:Npc, player: Player, widgetId: number, buttonId: number): RunnableHooks => { - //console.info(`pew pew you use magic on ${npc.name}!`); - - // Find all object action plugins that reference this location object - const matchingHooks = getActionHooks('magic_on_npc'); - - return { - hooks: matchingHooks, - actionPosition: player.position, - action: { - npc, - player, - widgetId, - buttonId - } - } - - -}; - - -/** - * Button action pipe definition. - */ -export default [ 'magic_on_npc', magicOnNpcActionPipe ] as ActionPipe; +import { Player, Npc } from '@engine/world/actor'; +import { ActionHook, getActionHooks, ActionPipe, RunnableHooks } from '@engine/action'; + + +/** + * Defines a button action hook. + */ +export interface MagicOnNPCActionHook extends ActionHook { + // The npc world id that was clicked on after choosing the spell + npcworldId?: number; + // The IDs of the UI widgets that the buttons are on. + widgetIds?: number[]; + // The child ID or list of child IDs of the button(s) within the UI widget. + buttonIds?: number | number[]; + // Whether or not this item action should cancel other running or queued actions. + cancelActions?: boolean; +} + + +/** + * The button action hook handler function to be called when the hook's conditions are met. + */ +export type magiconnpcActionHandler = (buttonAction: MagicOnNPCAction) => void | Promise; + + +/** + * Details about a button action being performed. + */ +export interface MagicOnNPCAction { + // The npc world id that was clicked on after choosing the spell + npc: Npc; + // The player performing the action. + player: Player; + // The ID of the UI widget that the button is on. + widgetId: number; + // The child ID of the button within the UI widget. + buttonId: number; +} + + +/** + * The pipe that the game engine hands button actions off to. + * @param npc + * @param player + * @param widgetId + * @param buttonId + */ +const magicOnNpcActionPipe = (npc:Npc, player: Player, widgetId: number, buttonId: number): RunnableHooks => { + //console.info(`pew pew you use magic on ${npc.name}!`); + + // Find all object action plugins that reference this location object + const matchingHooks = getActionHooks('magic_on_npc'); + + return { + hooks: matchingHooks, + actionPosition: player.position, + action: { + npc, + player, + widgetId, + buttonId + } + } + + +}; + + +/** + * Button action pipe definition. + */ +export default [ 'magic_on_npc', magicOnNpcActionPipe ] as ActionPipe; diff --git a/src/game-engine/world/action/move-item.action.ts b/src/engine/action/pipe/move-item.action.ts similarity index 78% rename from src/game-engine/world/action/move-item.action.ts rename to src/engine/action/pipe/move-item.action.ts index 8c4332bf1..82ebe69d9 100644 --- a/src/game-engine/world/action/move-item.action.ts +++ b/src/engine/action/pipe/move-item.action.ts @@ -1,8 +1,5 @@ -import { Player } from '@engine/world/actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { logger } from '@runejs/core'; -import { numberHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { ActionHook, getActionHooks, numberHookFilter, ActionPipe, RunnableHooks } from '@engine/action'; /** @@ -45,9 +42,13 @@ export interface MoveItemAction { * @param widget */ const moveItemActionPipe = (player: Player, fromSlot: number, toSlot: number, - widget: { widgetId: number, containerId: number }): RunnableHooks => { + widget: { widgetId: number, containerId: number }): RunnableHooks | null => { const matchingHooks = getActionHooks('move_item') - .filter(plugin => numberHookFilter(plugin.widgetId || plugin.widgetIds, widget.widgetId)); + .filter(plugin => ( + (plugin.widgetId || plugin.widgetIds) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + && numberHookFilter((plugin.widgetId || plugin.widgetIds)!, widget.widgetId) + )); if(!matchingHooks || matchingHooks.length === 0) { player.sendMessage(`Unhandled Move Item action: widget[${widget.widgetId}] container[${widget.containerId}] fromSlot[${fromSlot} toSlot${toSlot}`); diff --git a/src/game-engine/world/action/npc-init.action.ts b/src/engine/action/pipe/npc-init.action.ts similarity index 75% rename from src/game-engine/world/action/npc-init.action.ts rename to src/engine/action/pipe/npc-init.action.ts index 05bb228bb..8c27b1115 100644 --- a/src/game-engine/world/action/npc-init.action.ts +++ b/src/engine/action/pipe/npc-init.action.ts @@ -1,7 +1,5 @@ -import { Npc } from '@engine/world/actor/npc/npc'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { stringHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe } from '@engine/world/action/index'; +import { Npc } from '@engine/world/actor'; +import { ActionHook, getActionHooks, stringHookFilter, ActionPipe } from '@engine/action'; /** @@ -35,7 +33,13 @@ export interface NpcInitAction { const npcInitActionPipe = ({ npc }: NpcInitAction): void => { const actionHooks = getActionHooks('npc_init') .filter(plugin => (!plugin.npcs || stringHookFilter(plugin.npcs, npc.key))); - actionHooks.forEach(actionHook => actionHook.handler({ npc })); + actionHooks.forEach(actionHook => { + if (!actionHook.handler) { + return; + } + + actionHook.handler({ npc }); + }); }; diff --git a/src/game-engine/world/action/npc-interaction.action.ts b/src/engine/action/pipe/npc-interaction.action.ts similarity index 85% rename from src/game-engine/world/action/npc-interaction.action.ts rename to src/engine/action/pipe/npc-interaction.action.ts index fbbf05fe9..9fecffca4 100644 --- a/src/game-engine/world/action/npc-interaction.action.ts +++ b/src/engine/action/pipe/npc-interaction.action.ts @@ -1,10 +1,8 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { Position } from '@engine/world/position'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { playerWalkTo } from '@engine/game-server'; -import { stringHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player, Npc } from '@engine/world/actor'; +import { Position } from '@engine/world'; +import { + ActionHook, getActionHooks, stringHookFilter, questHookFilter, ActionPipe, RunnableHooks +} from '@engine/action'; /** @@ -48,13 +46,11 @@ export interface NpcInteractionAction { * @param position * @param option */ -const npcInteractionActionPipe = (player: Player, npc: Npc, position: Position, option: string): RunnableHooks => { +const npcInteractionActionPipe = (player: Player, npc: Npc, position: Position, option: string): RunnableHooks | null => { if(player.busy) { - return; + return null; } - - const morphedNpc = player.getMorphedNpcDetails(npc); // Find all NPC action plugins that reference this NPC @@ -63,7 +59,7 @@ const npcInteractionActionPipe = (player: Player, npc: Npc, position: Position, (!plugin.npcs || stringHookFilter(plugin.npcs, morphedNpc?.key || npc.key)) && (!plugin.options || stringHookFilter(plugin.options, option))); const questActions = matchingHooks.filter(plugin => plugin.questRequirement !== undefined); - + if(questActions.length !== 0) { matchingHooks = questActions; diff --git a/src/game-engine/world/action/object-interaction.action.ts b/src/engine/action/pipe/object-interaction.action.ts similarity index 88% rename from src/game-engine/world/action/object-interaction.action.ts rename to src/engine/action/pipe/object-interaction.action.ts index b84c7291a..93f0699e5 100644 --- a/src/game-engine/world/action/object-interaction.action.ts +++ b/src/engine/action/pipe/object-interaction.action.ts @@ -1,10 +1,9 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Position } from '@engine/world/position'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { playerWalkTo } from '@engine/game-server'; -import { advancedNumberHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; import { LandscapeObject, ObjectConfig } from '@runejs/filestore'; +import { Position } from '@engine/world'; +import { Player } from '@engine/world/actor'; +import { + ActionHook, getActionHooks, advancedNumberHookFilter, questHookFilter, ActionPipe, RunnableHooks +} from '@engine/action'; /** @@ -55,7 +54,7 @@ export interface ObjectInteractionAction { * @param cacheOriginal */ const objectInteractionActionPipe = (player: Player, landscapeObject: LandscapeObject, objectConfig: ObjectConfig, - position: Position, option: string, cacheOriginal: boolean): RunnableHooks => { + position: Position, option: string, cacheOriginal: boolean): RunnableHooks | null => { if(player.metadata.blockObjectInteractions) { return null; } diff --git a/src/game-engine/world/action/player-command.action.ts b/src/engine/action/pipe/player-command.action.ts similarity index 87% rename from src/game-engine/world/action/player-command.action.ts rename to src/engine/action/pipe/player-command.action.ts index ccdf45e9f..29d094348 100644 --- a/src/game-engine/world/action/player-command.action.ts +++ b/src/engine/action/pipe/player-command.action.ts @@ -1,6 +1,7 @@ -import { Player } from '../actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { ActionHook, getActionHooks, ActionPipe, RunnableHooks } from '@engine/action'; +import { reloadContent, reloadContentCommands } from '@engine/plugins/reload-content'; +import { logger } from '@runejs/common'; /** @@ -47,9 +48,15 @@ export interface PlayerCommandAction { * @param inputArgs */ const playerCommandActionPipe = (player: Player, command: string, isConsole: boolean, - inputArgs: string[]): RunnableHooks => { + inputArgs: string[]): RunnableHooks | null => { command = command.toLowerCase(); + // Reload game content + if (reloadContentCommands.indexOf(command) !== -1) { + reloadContent(player, isConsole).catch(logger.error); + return null; + } + const actionArgs = {}; const plugins = getActionHooks('player_command').filter(actionHook => { @@ -80,7 +87,7 @@ const playerCommandActionPipe = (player: Player, command: string, isConsole: boo for(let i = 0; i < actionHook.args.length; i++) { - let argValue: string | number = inputArgs[i] || null; + let argValue: string | number | null = inputArgs[i] || null; const pluginArg = actionHook.args[i]; if(argValue === null || argValue === undefined) { @@ -114,7 +121,7 @@ const playerCommandActionPipe = (player: Player, command: string, isConsole: boo if(plugins.length === 0) { player.sendLogMessage(`Unhandled command: ${ command }`, isConsole); - return; + return null; } return { diff --git a/src/game-engine/world/action/player-init.action.ts b/src/engine/action/pipe/player-init.action.ts similarity index 75% rename from src/game-engine/world/action/player-init.action.ts rename to src/engine/action/pipe/player-init.action.ts index 7125130c3..32ca66394 100644 --- a/src/game-engine/world/action/player-init.action.ts +++ b/src/engine/action/pipe/player-init.action.ts @@ -1,6 +1,5 @@ -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { Player } from '@engine/world/actor/player/player'; -import { ActionPipe } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { ActionHook, getActionHooks, ActionPipe } from '@engine/action'; /** @@ -30,7 +29,13 @@ export interface PlayerInitAction { */ const playerInitActionPipe = ({ player }: PlayerInitAction): void => { const actionHooks = getActionHooks('player_init'); - actionHooks.forEach(actionHook => actionHook.handler({ player })); + actionHooks.forEach(actionHook => { + if (!actionHook.handler) { + return; + } + + actionHook.handler({ player }); + }); }; diff --git a/src/game-engine/world/action/player-interaction.action.ts b/src/engine/action/pipe/player-interaction.action.ts similarity index 82% rename from src/game-engine/world/action/player-interaction.action.ts rename to src/engine/action/pipe/player-interaction.action.ts index e22ddeefa..e2df4d99a 100644 --- a/src/game-engine/world/action/player-interaction.action.ts +++ b/src/engine/action/pipe/player-interaction.action.ts @@ -1,10 +1,7 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Position } from '@engine/world/position'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { logger } from '@runejs/core'; -import { playerWalkTo } from '@engine/game-server'; -import { stringHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { Position } from '@engine/world'; +import { ActionHook, getActionHooks, stringHookFilter, questHookFilter, RunnableHooks } from '@engine/action'; +import { playerWalkTo } from '@engine/plugins'; /** @@ -45,7 +42,7 @@ export interface PlayerInteractionAction { * @param option */ const playerInteractionActionPipe = (player: Player, otherPlayer: Player, position: Position, - option: string): RunnableHooks => { + option: string): RunnableHooks | null => { // Find all player action plugins that reference this option let matchingHooks = getActionHooks('player_interaction') .filter(plugin => questHookFilter(player, plugin) && stringHookFilter(plugin.options, option)); diff --git a/src/game-engine/world/action/prayer.action.ts b/src/engine/action/pipe/prayer.action.ts similarity index 76% rename from src/game-engine/world/action/prayer.action.ts rename to src/engine/action/pipe/prayer.action.ts index e4eb0b6c8..71b4afe53 100644 --- a/src/game-engine/world/action/prayer.action.ts +++ b/src/engine/action/pipe/prayer.action.ts @@ -1,75 +1,72 @@ -import { Player } from '@engine/world/actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { advancedNumberHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; -import { Npc } from '../actor/npc/npc'; - - -/** - * Defines a button action hook. - */ -export interface PrayerActionHook extends ActionHook { - // The npc world id that was clicked on after choosing the spell - npcworldId?: number; - // The IDs of the UI widgets that the buttons are on. - widgetIds?: number[]; - // The child ID or list of child IDs of the button(s) within the UI widget. - buttonIds?: number | number[]; - // Whether or not this item action should cancel other running or queued actions. - cancelActions?: boolean; -} - - -/** - * The button action hook handler function to be called when the hook's conditions are met. - */ -export type PrayerActionHandler = (buttonAction: PrayerAction) => void | Promise; - - -/** - * Details about a button action being performed. - */ -export interface PrayerAction { - // The npc world id that was clicked on after choosing the spell - npc: Npc; - // The player performing the action. - player: Player; - // The ID of the UI widget that the button is on. - widgetId: number; - // The child ID of the button within the UI widget. - buttonId: number; -} - - -/** - * The pipe that the game engine hands button actions off to. - * @param npc - * @param player - * @param widgetId - * @param buttonId - */ -const PrayerActionPipe = (npc:Npc, player: Player, widgetId: number, buttonId: number): RunnableHooks => { - console.info(`You used prayer`); - - // Find all object action plugins that reference this location object - const matchingHooks = getActionHooks('button'); - - return { - hooks: matchingHooks, - actionPosition: player.position, - action: { - npc, - player, - widgetId, - buttonId - } - } - - -}; - - -/** - * Button action pipe definition. - */ -export default [ 'prayer', PrayerActionPipe ] as ActionPipe; +import { Player, Npc } from '@engine/world/actor'; +import { ActionHook, getActionHooks, ActionPipe, RunnableHooks } from '@engine/action'; + + +/** + * Defines a button action hook. + */ +export interface PrayerActionHook extends ActionHook { + // The npc world id that was clicked on after choosing the spell + npcworldId?: number; + // The IDs of the UI widgets that the buttons are on. + widgetIds?: number[]; + // The child ID or list of child IDs of the button(s) within the UI widget. + buttonIds?: number | number[]; + // Whether or not this item action should cancel other running or queued actions. + cancelActions?: boolean; +} + + +/** + * The button action hook handler function to be called when the hook's conditions are met. + */ +export type PrayerActionHandler = (buttonAction: PrayerAction) => void | Promise; + + +/** + * Details about a button action being performed. + */ +export interface PrayerAction { + // The npc world id that was clicked on after choosing the spell + npc: Npc; + // The player performing the action. + player: Player; + // The ID of the UI widget that the button is on. + widgetId: number; + // The child ID of the button within the UI widget. + buttonId: number; +} + + +/** + * The pipe that the game engine hands button actions off to. + * @param npc + * @param player + * @param widgetId + * @param buttonId + */ +const prayerActionPipe = (npc:Npc, player: Player, widgetId: number, buttonId: number): RunnableHooks => { + console.info(`You used prayer`); + + // Find all object action plugins that reference this location object + const matchingHooks = getActionHooks('button'); + + return { + hooks: matchingHooks, + actionPosition: player.position, + action: { + npc, + player, + widgetId, + buttonId + } + } + + +}; + + +/** + * Button action pipe definition. + */ +export default [ 'prayer', prayerActionPipe ] as ActionPipe; diff --git a/src/game-engine/world/action/region-change.action.ts b/src/engine/action/pipe/region-change.action.ts similarity index 89% rename from src/game-engine/world/action/region-change.action.ts rename to src/engine/action/pipe/region-change.action.ts index 4581ee837..a2fcb4adb 100644 --- a/src/game-engine/world/action/region-change.action.ts +++ b/src/engine/action/pipe/region-change.action.ts @@ -1,8 +1,7 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Coords, Position } from '@engine/world/position'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { RegionType } from '@engine/world/map/region'; -import { ActionPipe } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { Coords, Position } from '@engine/world'; +import { RegionType } from '@engine/world/map'; +import { ActionHook, getActionHooks, ActionPipe } from '@engine/action'; /** @@ -55,6 +54,10 @@ export interface RegionChangeAction { /** * Creates a RegionChangeAction object from the given inputs. + * + * TODO (Jameskmonger) I changed this function's return type to `| null` to satisfy TypeScript, + * not sure if this is correct or if the code was just wrong before. + * * @param player The player. * @param originalPosition The player's original position. * @param currentPosition The player's current position. @@ -62,7 +65,7 @@ export interface RegionChangeAction { */ export const regionChangeActionFactory = (player: Player, originalPosition: Position, currentPosition: Position, - teleporting: boolean = false): RegionChangeAction => { + teleporting: boolean = false): RegionChangeAction | null => { const regionTypes: RegionType[] = []; const originalMapRegionId: number = ((originalPosition.x >> 6) << 8) + (originalPosition.y >> 6); const currentMapRegionId: number = ((currentPosition.x >> 6) << 8) + (currentPosition.y >> 6); @@ -158,7 +161,10 @@ const regionChangeActionPipe = (actionData: RegionChangeAction): void => { actionList.forEach(async actionHook => new Promise(resolve => { - actionHook.handler(actionData); + if (actionHook && actionHook.handler) { + actionHook.handler(actionData); + } + resolve(); })); }; diff --git a/src/game-engine/world/action/spawned-item-interaction.action.ts b/src/engine/action/pipe/spawned-item-interaction.action.ts similarity index 81% rename from src/game-engine/world/action/spawned-item-interaction.action.ts rename to src/engine/action/pipe/spawned-item-interaction.action.ts index d7275cd67..2fe0619a8 100644 --- a/src/game-engine/world/action/spawned-item-interaction.action.ts +++ b/src/engine/action/pipe/spawned-item-interaction.action.ts @@ -1,12 +1,10 @@ -import { Player } from '@engine/world/actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { logger } from '@runejs/core'; -import { WorldItem } from '@engine/world/items/world-item'; -import { ItemDetails } from '@engine/config/item-config'; -import { findItem } from '@engine/config'; -import { playerWalkTo } from '@engine/game-server'; -import { numberHookFilter, stringHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { WorldItem } from '@engine/world'; +import { ItemDetails, findItem } from '@engine/config'; +import { + ActionHook, getActionHooks, numberHookFilter, stringHookFilter, questHookFilter, ActionPipe, RunnableHooks +} from '@engine/action'; +import { logger } from '@runejs/common'; /** @@ -47,7 +45,7 @@ export interface SpawnedItemInteractionAction { * @param worldItem * @param option */ -const spawnedItemInteractionPipe = (player: Player, worldItem: WorldItem, option: string): RunnableHooks => { +const spawnedItemInteractionPipe = (player: Player, worldItem: WorldItem, option: string): RunnableHooks | null => { // Find all world item action plugins that reference this world item let matchingHooks = getActionHooks('spawned_item_interaction').filter(plugin => { if(!questHookFilter(player, plugin)) { @@ -80,6 +78,11 @@ const spawnedItemInteractionPipe = (player: Player, worldItem: WorldItem, option const itemDetails = findItem(worldItem.itemId); + if(!itemDetails) { + logger.error(`Item ${worldItem.itemId} not registered on the server [spawned-item-interaction action pipe]`); + return null; + } + return { hooks: matchingHooks, actionPosition: worldItem.position, diff --git a/src/game-engine/world/action/widget-interaction.action.ts b/src/engine/action/pipe/widget-interaction.action.ts similarity index 90% rename from src/game-engine/world/action/widget-interaction.action.ts rename to src/engine/action/pipe/widget-interaction.action.ts index 75af8e2ea..ed1b9fb87 100644 --- a/src/game-engine/world/action/widget-interaction.action.ts +++ b/src/engine/action/pipe/widget-interaction.action.ts @@ -1,7 +1,7 @@ -import { Player } from '@engine/world/actor/player/player'; -import { ActionHook, getActionHooks } from '@engine/world/action/hooks'; -import { advancedNumberHookFilter, questHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ActionPipe, RunnableHooks } from '@engine/world/action/index'; +import { Player } from '@engine/world/actor'; +import { + ActionHook, getActionHooks, advancedNumberHookFilter, questHookFilter, ActionPipe, RunnableHooks +} from '@engine/action'; /** @@ -47,7 +47,7 @@ export interface WidgetInteractionAction { * @param childId The ID of the widget child being interacted with. * @param optionId The widget context option chosen by the player. */ -const widgetActionPipe = (player: Player, widgetId: number, childId: number, optionId: number): RunnableHooks => { +const widgetActionPipe = (player: Player, widgetId: number, childId: number, optionId: number): RunnableHooks | null => { const playerWidget = Object.values(player.interfaceState.widgetSlots) .find((widget) => widget && widget.widgetId === widgetId); diff --git a/src/game-engine/config/index.ts b/src/engine/config/config-handler.ts similarity index 72% rename from src/game-engine/config/index.ts rename to src/engine/config/config-handler.ts index 0e52d9bbe..e6e2e25bb 100644 --- a/src/game-engine/config/index.ts +++ b/src/engine/config/config-handler.ts @@ -1,12 +1,12 @@ -import { logger } from '@runejs/core'; +import 'json5/lib/register'; +import { logger } from '@runejs/common'; import _ from 'lodash'; import { ItemDetails, ItemPresetConfiguration, loadItemConfigurations, - translateItemConfig } from '@engine/config/item-config'; -import { filestore, questMap } from '@engine/game-server'; +import { filestore } from '@server/game/game-server'; import { loadNpcConfigurations, NpcDetails, @@ -15,17 +15,15 @@ import { } from '@engine/config/npc-config'; import { loadNpcSpawnConfigurations, NpcSpawn } from '@engine/config/npc-spawn-config'; import { loadShopConfigurations, Shop } from '@engine/config/shop-config'; -import { Quest } from '@engine/world/actor/player/quest'; +import { Quest } from '@engine/world/actor'; import { ItemSpawn, loadItemSpawnConfigurations } from '@engine/config/item-spawn-config'; -import { loadSkillGuideConfigurations, SkillGuide } from '@engine/config/skill-guide-config'; import { loadMusicRegionConfigurations, MusicTrack } from '@engine/config/music-regions-config'; -import { LandscapeObject, loadXteaRegionFiles, ObjectConfig, XteaRegion } from '@runejs/filestore'; - -require('json5/lib/register'); - +import { loadXteaRegionFiles, ObjectConfig, XteaRegion } from '@runejs/filestore'; +import { questMap } from '@engine/plugins'; export let itemMap: { [key: string]: ItemDetails }; +export let itemGroupMap: Record>; export let itemIdMap: { [key: number]: string }; export let objectMap: { [key: number]: ObjectConfig }; export let itemPresetMap: ItemPresetConfiguration; @@ -36,7 +34,6 @@ export let npcSpawns: NpcSpawn[] = []; export let musicRegions: MusicTrack[] = []; export let itemSpawns: ItemSpawn[] = []; export let shopMap: { [key: string]: Shop }; -export let skillGuides: SkillGuide[] = []; export let xteaRegions: { [key: number]: XteaRegion }; export const musicRegionMap = new Map(); @@ -49,8 +46,9 @@ export async function loadCoreConfigurations(): Promise { export async function loadGameConfigurations(): Promise { logger.info(`Loading server configurations...`); - const { items, itemIds, itemPresets } = await loadItemConfigurations('data/config/items/'); + const { items, itemIds, itemPresets, itemGroups } = await loadItemConfigurations('data/config/items/'); itemMap = items; + itemGroupMap = itemGroups; itemIdMap = itemIds; itemPresetMap = itemPresets; @@ -65,12 +63,52 @@ export async function loadGameConfigurations(): Promise { itemSpawns = await loadItemSpawnConfigurations('data/config/item-spawns/'); shopMap = await loadShopConfigurations('data/config/shops/'); - skillGuides = await loadSkillGuideConfigurations('data/config/skill-guides/'); objectMap = {}; logger.info(`Loaded ${musicRegions.length} music regions, ${Object.keys(itemMap).length} items, ${itemSpawns.length} item spawns, ` + - `${Object.keys(npcMap).length} npcs, ${npcSpawns.length} npc spawns, ${Object.keys(shopMap).length} shops and ${skillGuides.length} skill guides.`); + `${Object.keys(npcMap).length} npcs, ${npcSpawns.length} npc spawns, and ${Object.keys(shopMap).length} shops.`); +} + + +/** + * find all items in all select groups + * @param groupKeys array of string of which to find items connected with + * @return itemsKeys array of itemkeys in all select groups + */ +export const findItemTagsInGroups = (groupKeys: string[]): string[] => { + return Object.keys(groupKeys.reduce>((all, groupKey)=> { + const items = itemGroupMap[groupKey] || {}; + return { ...all, ...items }; + }, {})); +} + + +/** + * find all items which are shared by all the groups, and discard items not in all groups + * @param groupKeys groups keys which to find items shared by + * @return itemKeys of items shared by all groups + */ +export const findItemTagsInGroupFilter = (groupKeys: string[]): string[] => { + if(!groupKeys || groupKeys.length === 0) { + return []; + } + let collection: Record | undefined = undefined; + groupKeys.forEach((groupKey) => { + if(!collection) { + collection = { ...(itemGroupMap[groupKey] || {}) }; + return; + } + const current = itemGroupMap[groupKey] || {}; + + Object.keys(collection).forEach((existingItemKey) => { + if(!(existingItemKey in current) && collection) { + delete collection[existingItemKey]; + } + }); + }); + + return Object.keys(collection || {}); } @@ -79,7 +117,7 @@ export const findItem = (itemKey: number | string): ItemDetails | null => { return null; } - let gameId: number; + let gameId: number | null = null; if(typeof itemKey === 'number') { gameId = itemKey; itemKey = itemIdMap[gameId]; @@ -100,20 +138,6 @@ export const findItem = (itemKey: number | string): ItemDetails | null => { if(item?.gameId) { gameId = item.gameId; } - - if(item?.extends) { - let extensions = item.extends; - if(typeof extensions === 'string') { - extensions = [ extensions ]; - } - - extensions.forEach(extKey => { - const extensionItem = itemPresetMap[extKey]; - if(extensionItem) { - item = _.merge(item, translateItemConfig(undefined, extensionItem)); - } - }); - } } if(gameId) { @@ -199,7 +223,9 @@ export const findShop = (shopKey: string): Shop | null => { export const findQuest = (questId: string): Quest | null => { - return questMap[Object.keys(questMap).find(quest => quest.toLocaleLowerCase() === questId.toLocaleLowerCase())] || null; + const questKey = Object.keys(questMap).find(quest => quest.toLocaleLowerCase() === questId.toLocaleLowerCase()); + + return questKey ? questMap[questKey] : null; }; export const findMusicTrack = (trackId: number): MusicTrack | null => { @@ -211,5 +237,5 @@ export const findMusicTrackByButtonId = (buttonId: number): MusicTrack | null => }; export const findSongIdByRegionId = (regionId: number): number | null => { - return musicRegionMap.has(regionId) ? musicRegionMap.get(regionId) : null; + return musicRegionMap.get(regionId) || null; }; diff --git a/src/game-engine/config/data-dump.ts b/src/engine/config/data-dump.ts similarity index 91% rename from src/game-engine/config/data-dump.ts rename to src/engine/config/data-dump.ts index 0115c4ea7..6fd6dfcc2 100644 --- a/src/game-engine/config/data-dump.ts +++ b/src/engine/config/data-dump.ts @@ -1,7 +1,7 @@ import { join } from 'path'; import { writeFileSync } from 'fs'; -import { filestore } from '@engine/game-server'; -import { logger } from '@runejs/core'; +import { filestore } from '@server/game/game-server'; +import { logger } from '@runejs/common'; import { ItemConfig, NpcConfig, ObjectConfig, WidgetBase } from '@runejs/filestore'; @@ -14,7 +14,7 @@ export interface DataDumpResult { function dump(fileName: string, definitions: T[]): DataDumpResult { const filePath = join('data/dump', fileName); - const arr = []; + const arr: T[] = []; for(let i = 0; i < definitions.length; i++) { arr.push(definitions[i]); } diff --git a/src/engine/config/directories.ts b/src/engine/config/directories.ts new file mode 100644 index 000000000..66d759c61 --- /dev/null +++ b/src/engine/config/directories.ts @@ -0,0 +1,3 @@ +import { join } from 'path'; + +export const BUILD_DIR = join('.', 'dist', 'engine'); diff --git a/src/engine/config/index.ts b/src/engine/config/index.ts new file mode 100644 index 000000000..3f9a0a16b --- /dev/null +++ b/src/engine/config/index.ts @@ -0,0 +1,9 @@ +export * from './config-handler'; +export * from './item-config'; +export * from './item-spawn-config'; +export * from './music-regions-config'; +export * from './npc-config'; +export * from './npc-spawn-config'; +export * from './quest-config'; +export * from './shop-config'; +export * from './directories'; diff --git a/src/game-engine/config/item-config.ts b/src/engine/config/item-config.ts similarity index 63% rename from src/game-engine/config/item-config.ts rename to src/engine/config/item-config.ts index ce76a0beb..4b70dd51e 100644 --- a/src/game-engine/config/item-config.ts +++ b/src/engine/config/item-config.ts @@ -1,7 +1,7 @@ -import { loadConfigurationFiles } from '@runejs/core/fs'; +import { loadConfigurationFiles } from '@runejs/common/fs'; import { SkillName } from '@engine/world/actor/skills'; -import _ from 'lodash'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; +import { deepMerge } from '@engine/util/objects'; export type WeaponStyle = 'axe' | 'hammer' | 'bow' | 'claws' | 'crossbow' | 'longsword' @@ -125,6 +125,7 @@ export interface ItemConfiguration { equippable?: boolean; consumable?: boolean; destroy?: string | boolean; + groups?: string[]; equipment_data?: { equipment_slot: EquipmentSlot; equipment_type?: EquipmentType; @@ -155,6 +156,7 @@ export class ItemDetails { consumable?: boolean; stackable: boolean = false; value: number = 0; + groups: string[] = []; members: boolean = false; groundOptions: string[] = []; inventoryOptions: string[] = []; @@ -184,7 +186,7 @@ export class ItemDetails { } } -export function translateItemConfig(key: string, config: ItemConfiguration): any { +export function translateItemConfig(key: string | undefined, config: ItemConfiguration): any { return { key, extends: config.extends || undefined, @@ -194,6 +196,7 @@ export function translateItemConfig(key: string, config: ItemConfiguration): any equippable: config.equippable, weight: config.weight, destroy: config.destroy || undefined, + groups: config.groups || [], consumable: config.consumable, equipmentData: config.equipment_data ? { equipmentType: config.equipment_data?.equipment_type || undefined, @@ -209,12 +212,14 @@ export function translateItemConfig(key: string, config: ItemConfiguration): any } export async function loadItemConfigurations(path: string): Promise<{ items: { [key: string]: ItemDetails }; - itemIds: { [key: number]: string }; itemPresets: ItemPresetConfiguration; }> { + itemIds: { [key: number]: string }; itemPresets: ItemPresetConfiguration; itemGroups: Record>; }> { const itemIds: { [key: number]: string } = {}; const items: { [key: string]: ItemDetails } = {}; + const itemGroups : Record> = {} // Record where key is group id, and value is an array of all itemstags in group let itemPresets: ItemPresetConfiguration = {}; const files = await loadConfigurationFiles(path); + const itemConfigurations: Record = {}; files.forEach(itemConfigs => { const itemKeys = Object.keys(itemConfigs); @@ -222,30 +227,78 @@ export async function loadItemConfigurations(path: string): Promise<{ items: { [ if(key === 'presets') { itemPresets = { ...itemPresets, ...itemConfigs[key] }; } else { + itemConfigurations[key] = itemConfigs[key] as ItemConfiguration; + } + }); + }); + Object.entries(itemConfigurations).forEach(([key, itemConfig]) => { + if(itemConfig.game_id !== undefined && !isNaN(itemConfig.game_id)) { + itemIds[itemConfig.game_id] = key; + let item = { ...translateItemConfig(key, itemConfig) } + if(item?.extends) { + let extensions = item.extends; + if(typeof extensions === 'string') { + extensions = [ extensions ]; + } - const itemConfig: ItemConfiguration = itemConfigs[key] as ItemConfiguration; - if(!isNaN(itemConfig.game_id)) { - itemIds[itemConfig.game_id] = key; - items[key] = { ...translateItemConfig(key, itemConfig) }; + extensions.forEach(extKey => { + const extensionItem = itemPresets[extKey]; + if(extensionItem) { + const preset = translateItemConfig(undefined, extensionItem); + item = deepMerge(item, preset); + } + }); + } + items[key] = item; + item.groups.forEach((group) => { + if(!itemGroups[group]) { + itemGroups[group] = {}; } + itemGroups[group][key] = true; + }) + } - if(itemConfig.variations) { - for(const subItem of itemConfig.variations) { - const subKey = subItem.suffix ? key + ':' + subItem.suffix : key; - const baseItem = JSON.parse(JSON.stringify({ ...translateItemConfig(key, itemConfig) })); - const subBaseItem = JSON.parse(JSON.stringify({ ...translateItemConfig(subKey, subItem) })); - itemIds[subItem.game_id] = subKey; - - if(!items[subKey]) { - items[subKey] = _.merge(baseItem, subBaseItem); - } else { - logger.warn(`Duplicate item key ${subKey} found - the item was not loaded.`); + if(itemConfig.variations) { + for(const subItem of itemConfig.variations) { + if (!subItem.game_id) { + logger.warn(`Item ${key} has a variation without a game_id. Skipping.`); + continue; + } + + const subKey = subItem.suffix ? key + ':' + subItem.suffix : key; + const baseItem = JSON.parse(JSON.stringify({ ...translateItemConfig(key, itemConfig) })); + const subBaseItem = JSON.parse(JSON.stringify({ ...translateItemConfig(subKey, subItem) })); + itemIds[subItem.game_id] = subKey; + + if(!items[subKey]) { + let item = deepMerge(baseItem, subBaseItem); + if(item?.extends) { + let extensions = item.extends; + if(typeof extensions === 'string') { + extensions = [ extensions ]; } + + extensions.forEach(extKey => { + const extensionItem = itemPresets[extKey]; + if(extensionItem) { + const preset = translateItemConfig(undefined, extensionItem); + item = deepMerge(item, preset); + } + }); } + items[subKey] = item; + items[subKey].groups.forEach((group) => { + if(!itemGroups[group]) { + itemGroups[group] = {}; + } + itemGroups[group][subKey] = true; + }) + } else { + logger.warn(`Duplicate item key ${subKey} found - the item was not loaded.`); } } - }); - }); + } + }) - return { items, itemIds, itemPresets }; + return { items, itemIds, itemPresets, itemGroups }; } diff --git a/src/game-engine/config/item-spawn-config.ts b/src/engine/config/item-spawn-config.ts similarity index 93% rename from src/game-engine/config/item-spawn-config.ts rename to src/engine/config/item-spawn-config.ts index af7cd4bde..bc31c688e 100644 --- a/src/game-engine/config/item-spawn-config.ts +++ b/src/engine/config/item-spawn-config.ts @@ -1,5 +1,5 @@ import { Position } from '@engine/world/position'; -import { loadConfigurationFiles } from '@runejs/core/fs'; +import { loadConfigurationFiles } from '@runejs/common/fs'; export interface ItemSpawnConfiguration { @@ -48,7 +48,7 @@ export function translateItemSpawnConfig(config: ItemSpawnConfiguration): ItemSp } export async function loadItemSpawnConfigurations(path: string): Promise { - const itemSpawns = []; + const itemSpawns: ItemSpawn[] = []; const files = await loadConfigurationFiles(path); files.forEach(spawns => spawns.forEach(itemSpawn => itemSpawns.push(translateItemSpawnConfig(itemSpawn)))); diff --git a/src/game-engine/config/music-regions-config.ts b/src/engine/config/music-regions-config.ts similarity index 96% rename from src/game-engine/config/music-regions-config.ts rename to src/engine/config/music-regions-config.ts index 6a5dc94b5..35abf0665 100644 --- a/src/game-engine/config/music-regions-config.ts +++ b/src/engine/config/music-regions-config.ts @@ -28,7 +28,7 @@ export function translateMusicRegionsConfig(config: MusicRegionsConfiguration): } export async function loadMusicRegionConfigurations(): Promise { - const regions = []; + const regions: MusicTrack[] = []; await musicRegionsFile.musicRegions.forEach(musicRegion => regions.push(translateMusicRegionsConfig(musicRegion))); return regions; diff --git a/src/game-engine/config/npc-config.ts b/src/engine/config/npc-config.ts similarity index 94% rename from src/game-engine/config/npc-config.ts rename to src/engine/config/npc-config.ts index 9511548d4..fe1cfee69 100644 --- a/src/game-engine/config/npc-config.ts +++ b/src/engine/config/npc-config.ts @@ -1,10 +1,10 @@ import { DefensiveBonuses } from '@engine/config/item-config'; -import { loadConfigurationFiles } from '@runejs/core/fs'; -import { filestore } from '@engine/game-server'; +import { loadConfigurationFiles } from '@runejs/common/fs'; +import { filestore } from '@server/game/game-server'; import _ from 'lodash'; import { NpcConfig } from '@runejs/filestore'; -import { logger } from '@runejs/core'; -import { QuestRequirement } from '@engine/world/action'; +import { logger } from '@runejs/common'; +import { QuestRequirement } from '@engine/action'; export interface NpcSkills { @@ -86,7 +86,7 @@ export class NpcDetails extends NpcConfig { } -export function translateNpcServerConfig(npcKey: string, config: NpcServerConfig): NpcDetails { +export function translateNpcServerConfig(npcKey: string | undefined, config: NpcServerConfig): NpcDetails { return new NpcDetails({ key: npcKey, extends: config.extends || undefined, diff --git a/src/game-engine/config/npc-spawn-config.ts b/src/engine/config/npc-spawn-config.ts similarity index 92% rename from src/game-engine/config/npc-spawn-config.ts rename to src/engine/config/npc-spawn-config.ts index 6bd6da058..f8aaecea6 100644 --- a/src/game-engine/config/npc-spawn-config.ts +++ b/src/engine/config/npc-spawn-config.ts @@ -1,5 +1,5 @@ import { Position } from '@engine/world/position'; -import { loadConfigurationFiles } from '@runejs/core/fs'; +import { loadConfigurationFiles } from '@runejs/common/fs'; import { Direction } from '@engine/world/direction'; @@ -35,7 +35,7 @@ export function translateNpcSpawnConfig(config: NpcSpawnConfiguration): NpcSpawn } export async function loadNpcSpawnConfigurations(path: string): Promise { - const npcSpawns = []; + const npcSpawns: NpcSpawn[] = []; const files = await loadConfigurationFiles(path); files.forEach(spawns => spawns.forEach(npcSpawn => npcSpawns.push(translateNpcSpawnConfig(npcSpawn)))); diff --git a/src/game-engine/config/quest-config.ts b/src/engine/config/quest-config.ts similarity index 73% rename from src/game-engine/config/quest-config.ts rename to src/engine/config/quest-config.ts index 5906a5d85..24725a669 100644 --- a/src/game-engine/config/quest-config.ts +++ b/src/engine/config/quest-config.ts @@ -1,8 +1,6 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; -import { logger } from '@runejs/core'; -import { handleTutorial } from '@plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin'; +import { logger } from '@runejs/common'; +import { Npc, Player } from '@engine/world/actor'; +import { npcInteractionActionHandler } from '@engine/action'; export type QuestKey = number | 'complete'; @@ -42,7 +40,9 @@ export class PlayerQuest { } } -export function questDialogueActionFactory(questId: string, npcDialogueHandler: QuestDialogueHandler): npcInteractionActionHandler { +export function questDialogueActionFactory(questId: string, + npcDialogueHandler: QuestDialogueHandler, + stageHandler: (player: Player) => Promise): npcInteractionActionHandler { return async({ player, npc }) => { const quest = player.getQuest(questId); if(!quest) { @@ -58,7 +58,7 @@ export function questDialogueActionFactory(questId: string, npcDialogueHandler: logger.error(e); } - await handleTutorial(player); + await stageHandler(player); } }; } diff --git a/src/game-engine/config/shop-config.ts b/src/engine/config/shop-config.ts similarity index 87% rename from src/game-engine/config/shop-config.ts rename to src/engine/config/shop-config.ts index 26d84a97b..1f1e48720 100644 --- a/src/game-engine/config/shop-config.ts +++ b/src/engine/config/shop-config.ts @@ -1,9 +1,9 @@ import { ContainerUpdateEvent, ItemContainer } from '@engine/world/items/item-container'; -import { findItem, widgets } from '@engine/config/index'; -import { loadConfigurationFiles } from '@runejs/core/fs'; +import { findItem, widgets } from '@engine/config/config-handler'; +import { loadConfigurationFiles } from '@runejs/common/fs'; import { Player } from '@engine/world/actor/player/player'; import { ItemDetails } from '@engine/config/item-config'; -import { WidgetClosedEvent } from '@engine/world/actor/player/interface-state'; +import { WidgetClosedEvent } from '@engine/interface'; import { Subscription } from 'rxjs'; @@ -59,7 +59,11 @@ export class Shop { const itemStock = this.container.amount(item.gameId); if(itemSoldHere) { - originalStockAmount = this.originalStock.find(stock => stock && stock[0] === itemKey)[1]; + const foundStock = this.originalStock.find(stock => stock && stock[0] === itemKey); + + if (foundStock) { + originalStockAmount = foundStock[1]; + } } else if(!this.generalStore) { return -1; // Can not sell this item to this shop (shop is not a general store!) } @@ -97,8 +101,8 @@ export class Shop { } public open(player: Player): void { - player.metadata['lastOpenedShop'] = this; - player.metadata['shopCloseListener'] = player.interfaceState.closed.subscribe((whatClosed: WidgetClosedEvent) => { + player.metadata.lastOpenedShop = this; + player.metadata.shopCloseListener = player.interfaceState.closed.subscribe((whatClosed: WidgetClosedEvent) => { if(whatClosed && whatClosed.widget && whatClosed.widget.widgetId === widgets.shop.widgetId) { this.removePlayerFromShop(player); } @@ -121,7 +125,7 @@ export class Shop { private updateCustomers() { for (const player of this.customers) { - if(player.metadata['lastOpenedShop'] === this) { + if(player.metadata.lastOpenedShop === this) { player.outgoingPackets.sendUpdateAllWidgetItems(widgets.shop, this.container); } else { this.removePlayerFromShop(player); @@ -130,9 +134,10 @@ export class Shop { } private removePlayerFromShop(player: Player) { - if(player.metadata['lastOpenedShop'] === this) { - player.metadata['lastOpenedShop'] = undefined; - player.metadata['shopCloseListener'].unsubscribe(); + if(player.metadata.lastOpenedShop === this) { + player.metadata.lastOpenedShop = undefined; + + player.metadata.shopCloseListener?.unsubscribe(); } this.customers = this.customers.filter((c) => c !== player); } diff --git a/src/engine/interface/index.ts b/src/engine/interface/index.ts new file mode 100644 index 000000000..c3f32cb76 --- /dev/null +++ b/src/engine/interface/index.ts @@ -0,0 +1 @@ +export * from './interface-state'; diff --git a/src/game-engine/world/actor/player/interface-state.ts b/src/engine/interface/interface-state.ts similarity index 93% rename from src/game-engine/world/actor/player/interface-state.ts rename to src/engine/interface/interface-state.ts index 7faed6649..2a1bbf637 100644 --- a/src/game-engine/world/actor/player/interface-state.ts +++ b/src/engine/interface/interface-state.ts @@ -1,5 +1,6 @@ import { Player } from '@engine/world/actor/player/player'; import { ItemContainer } from '@engine/world/items/item-container'; +import { logger } from '@runejs/common'; import { lastValueFrom, Subject } from 'rxjs'; import { filter, take } from 'rxjs/operators'; @@ -45,7 +46,7 @@ export class Widget { public multi: boolean = false; public queued: boolean = false; public containerId: number; - public container: ItemContainer = null; + public container: ItemContainer | null = null; public fakeWidget?: number; public metadata: { [key: string]: any }; @@ -133,7 +134,17 @@ export class InterfaceState { } public closeWidget(slot: GameInterfaceSlot, widgetId?: number, data?: number): void { - const widget: Widget | null = (slot ? this.widgetSlots[slot] : this.findWidget(widgetId)) || null; + let widget: Widget | null = null; + + if (slot) { + widget = this.widgetSlots[slot]; + } else { + if (!widgetId) { + throw new Error('Invalid widget close request: no slot or widgetId provided'); + } + + widget = this.findWidget(widgetId); + } if(!widget) { return; @@ -193,7 +204,7 @@ export class InterfaceState { public findWidget(widgetId: number): Widget | null { const slots: GameInterfaceSlot[] = Object.keys(this.widgetSlots) as GameInterfaceSlot[]; - let widget: Widget; + let widget: Widget | null = null; slots.forEach(slot => { if(this.widgetSlots[slot]?.widgetId === widgetId) { widget = this.widgetSlots[slot]; @@ -252,6 +263,12 @@ export class InterfaceState { } } else if(slot === 'tabarea') { const screenWidget = this.getWidget('screen'); + + if (!screenWidget) { + logger.error(`Tried to open tab widget ${widgetId} without a screen widget open`); + return; + } + if(multi) { packets.showScreenAndTabWidgets(screenWidget.widgetId, widgetId); } else { diff --git a/src/game-engine/net/inbound-packets.ts b/src/engine/net/inbound-packet-handler.ts similarity index 83% rename from src/game-engine/net/inbound-packets.ts rename to src/engine/net/inbound-packet-handler.ts index 78d258ad4..2c3ebf172 100644 --- a/src/game-engine/net/inbound-packets.ts +++ b/src/engine/net/inbound-packet-handler.ts @@ -1,8 +1,8 @@ import { Player } from '../world/actor/player/player'; -import { logger } from '@runejs/core'; -import { ByteBuffer } from '@runejs/core/buffer'; +import { logger } from '@runejs/common'; +import { ByteBuffer } from '@runejs/common'; import { getFiles } from '../util/files'; -import { gameEngineDist } from '@engine/util/directories'; +import { BUILD_DIR } from '@engine/config'; interface InboundPacket { opcode: number; @@ -18,12 +18,12 @@ export interface PacketData { export const incomingPackets = new Map(); -export const PACKET_DIRECTORY = `${gameEngineDist}/net/inbound-packets`; +export const PACKET_DIRECTORY = `${BUILD_DIR}/net/inbound-packets`; export async function loadPackets(): Promise> { incomingPackets.clear(); - for await(const path of getFiles(PACKET_DIRECTORY, ['.js'], true)) { + for await(const path of getFiles(PACKET_DIRECTORY, ['.packet.js'], true)) { const location = './inbound-packets' + path.substring(PACKET_DIRECTORY.length).replace('.js', ''); const packet = require(location).default; if (Array.isArray(packet)) { diff --git a/src/engine/net/inbound-packets/add-friend.packet.ts b/src/engine/net/inbound-packets/add-friend.packet.ts new file mode 100644 index 000000000..e080fc12e --- /dev/null +++ b/src/engine/net/inbound-packets/add-friend.packet.ts @@ -0,0 +1,11 @@ +import { PacketData } from '@engine/net'; +import { longToString } from '@engine/util'; +import { Player } from '@engine/world/actor'; + + +export default { + opcode: 114, + size: 8, + handler: (player: Player, packet: PacketData) => + player.addFriend(longToString(BigInt(packet.buffer.get('LONG')))) +}; diff --git a/src/engine/net/inbound-packets/add-ignore.packet.ts b/src/engine/net/inbound-packets/add-ignore.packet.ts new file mode 100644 index 000000000..eb4829b65 --- /dev/null +++ b/src/engine/net/inbound-packets/add-ignore.packet.ts @@ -0,0 +1,10 @@ +import { longToString } from '@engine/util'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +export default { + opcode: 251, + size: 8, + handler: (player: Player, packet: PacketData) => + player.addIgnoredPlayer(longToString(BigInt(packet.buffer.get('LONG')))) +}; diff --git a/src/engine/net/inbound-packets/blinking-tab-click.packet.ts b/src/engine/net/inbound-packets/blinking-tab-click.packet.ts new file mode 100644 index 000000000..5728de0b4 --- /dev/null +++ b/src/engine/net/inbound-packets/blinking-tab-click.packet.ts @@ -0,0 +1,21 @@ +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +const blinkingTabClickPacket = (player: Player, packet: PacketData) => { + const { buffer } = packet; + const tabIndex = buffer.get('byte'); + + const tabClickEventIndex = player.metadata?.tabClickEvent?.tabIndex || -1; + + if(tabClickEventIndex === tabIndex) { + if (player.metadata.tabClickEvent) { + player.metadata.tabClickEvent.event.next(true); + } + } +}; + +export default { + opcode: 44, + size: 1, + handler: blinkingTabClickPacket +}; diff --git a/src/game-engine/net/inbound-packets/button-click-packet.js b/src/engine/net/inbound-packets/button-click.packet.ts similarity index 63% rename from src/game-engine/net/inbound-packets/button-click-packet.js rename to src/engine/net/inbound-packets/button-click.packet.ts index 2525a16e8..f74d72f03 100644 --- a/src/game-engine/net/inbound-packets/button-click-packet.js +++ b/src/engine/net/inbound-packets/button-click.packet.ts @@ -1,4 +1,7 @@ -const buttonClickPacket = (player, packet) => { +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +const buttonClickPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; const widgetId = buffer.get('short'); const buttonId = buffer.get('short'); diff --git a/src/game-engine/net/inbound-packets/character-design-packet.ts b/src/engine/net/inbound-packets/character-design.packet.ts similarity index 80% rename from src/game-engine/net/inbound-packets/character-design-packet.ts rename to src/engine/net/inbound-packets/character-design.packet.ts index 3d040d180..c33bcec5f 100644 --- a/src/game-engine/net/inbound-packets/character-design-packet.ts +++ b/src/engine/net/inbound-packets/character-design.packet.ts @@ -1,5 +1,5 @@ -import { Player } from '@engine/world/actor/player/player'; -import { PacketData } from '@engine/net/inbound-packets'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; const characterDesignPacket = (player: Player, packet: PacketData) => { @@ -7,16 +7,16 @@ const characterDesignPacket = (player: Player, packet: PacketData) => { // @TODO verify validity of selections - const gender = buffer.get(); + const gender = buffer.get('byte'); const models = new Array(7); const colors = new Array(5); for(let i = 0; i < models.length; i++) { - models[i] = buffer.get(); + models[i] = buffer.get('byte'); } for(let i = 0; i < colors.length; i++) { - colors[i] = buffer.get(); + colors[i] = buffer.get('byte'); } player.appearance = { diff --git a/src/game-engine/net/inbound-packets/chat-packet.js b/src/engine/net/inbound-packets/chat.packet.ts similarity index 52% rename from src/game-engine/net/inbound-packets/chat-packet.js rename to src/engine/net/inbound-packets/chat.packet.ts index 04e367e30..f95ef0a9b 100644 --- a/src/game-engine/net/inbound-packets/chat-packet.js +++ b/src/engine/net/inbound-packets/chat.packet.ts @@ -1,8 +1,11 @@ -const chatPacket = (player, packet) => { +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +const chatPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; - buffer.get(); - const color = buffer.get(); - const effects = buffer.get(); + buffer.get('byte'); + const color = buffer.get('byte'); + const effects = buffer.get('byte'); const data = Buffer.from(buffer.getSlice(buffer.readerIndex, buffer.length - buffer.readerIndex)); player.updateFlags.addChatMessage({ color, effects, data }); }; diff --git a/src/engine/net/inbound-packets/chatbox-request-response-packet.ts b/src/engine/net/inbound-packets/chatbox-request-response-packet.ts new file mode 100644 index 000000000..5bc28439a --- /dev/null +++ b/src/engine/net/inbound-packets/chatbox-request-response-packet.ts @@ -0,0 +1,35 @@ +import { world } from '@engine/game-server'; +import { World } from '@engine/world'; +import { logger } from '@runejs/core'; +import { Player, playerOptions } from '@engine/world/actor/player/player'; +import { PacketData } from '@engine/net/inbound-packets'; + +const chatboxRequestResponsePacket = (player: Player, packet: PacketData) => { + const { buffer } = packet; + const playerIndex = buffer.get('short', 'u', 'be') - 1; + + if(playerIndex < 0 || playerIndex > World.MAX_PLAYERS - 1) { + return; + } + + const otherPlayer = world.playerList[playerIndex]; + if(!otherPlayer) { + return; + } + + const position = otherPlayer.position; + const distance = Math.floor(position.distanceBetween(player.position)); + + // Too far away + if(distance > 16) { + return; + } + + player.actionPipeline.call('player_interaction', player, otherPlayer, position, 'request_response'); +}; + +export default { + opcode: 96, + size: 2, + handler: chatboxRequestResponsePacket +}; diff --git a/src/game-engine/net/inbound-packets/command-packet.js b/src/engine/net/inbound-packets/command.packet.ts similarity index 80% rename from src/game-engine/net/inbound-packets/command-packet.js rename to src/engine/net/inbound-packets/command.packet.ts index 72bf36c29..8dbd1eb51 100644 --- a/src/game-engine/net/inbound-packets/command-packet.js +++ b/src/engine/net/inbound-packets/command.packet.ts @@ -1,6 +1,7 @@ -import { Rights } from '../../world/actor/player/player'; +import { Player, Rights } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; -const commandPacket = (player, packet) => { +const commandPacket = (player: Player, packet: PacketData) => { const input = packet.buffer.getString(); if(!input || input.trim().length === 0) { diff --git a/src/game-engine/net/inbound-packets/drop-item-packet.js b/src/engine/net/inbound-packets/drop-item.packet.ts similarity index 73% rename from src/game-engine/net/inbound-packets/drop-item-packet.js rename to src/engine/net/inbound-packets/drop-item.packet.ts index d0376b6f1..fe68b402f 100644 --- a/src/game-engine/net/inbound-packets/drop-item-packet.js +++ b/src/engine/net/inbound-packets/drop-item.packet.ts @@ -1,4 +1,7 @@ -const dropItemPacket = (player, packet) => { +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +const dropItemPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; const widgetId = buffer.get('short', 'u', 'le'); const containerId = buffer.get('short', 'u', 'le'); diff --git a/src/game-engine/net/inbound-packets/examine-packet.js b/src/engine/net/inbound-packets/examine.packet.ts similarity index 57% rename from src/game-engine/net/inbound-packets/examine-packet.js rename to src/engine/net/inbound-packets/examine.packet.ts index fd2022caf..653daf85d 100644 --- a/src/game-engine/net/inbound-packets/examine-packet.js +++ b/src/engine/net/inbound-packets/examine.packet.ts @@ -1,17 +1,19 @@ -import { world } from '../../game-server'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; +import { activeWorld } from '@engine/world'; -const examinePacket = (player, packet) => { +const examinePacket = (player: Player, packet: PacketData) => { const { packetId, buffer } = packet; const id = buffer.get('short', 's', 'le'); let message; if(packetId === 151) { - message = world.examine.getItem(id); + message = activeWorld.examine.getItem(id); } else if(packetId === 148) { - message = world.examine.getObject(id); + message = activeWorld.examine.getObject(id); } else if(packetId === 247) { - message = world.examine.getNpc(id); + message = activeWorld.examine.getNpc(id); } if(message) { diff --git a/src/game-engine/net/inbound-packets/item-interaction-packet.js b/src/engine/net/inbound-packets/item-interaction.packet.ts similarity index 94% rename from src/game-engine/net/inbound-packets/item-interaction-packet.js rename to src/engine/net/inbound-packets/item-interaction.packet.ts index fd37be6c4..714bb8bb1 100644 --- a/src/game-engine/net/inbound-packets/item-interaction-packet.js +++ b/src/engine/net/inbound-packets/item-interaction.packet.ts @@ -1,4 +1,6 @@ -import { getItemOption } from '../../world/items/item'; +import { getItemOption } from '@engine/world'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; const option1 = buffer => { const itemId = buffer.get('short', 'u'); @@ -56,7 +58,7 @@ const inventoryOption4 = buffer => { return { widgetId, containerId, itemId, slot }; }; -const itemInteractionPacket = (player, packet) => { +const itemInteractionPacket = (player: Player, packet: PacketData) => { const { packetId } = packet; const packets = { 38: { packetDef: option1, optionNumber: 1 }, diff --git a/src/game-engine/net/inbound-packets/item-on-item-packet.js b/src/engine/net/inbound-packets/item-on-item.packet.ts similarity index 78% rename from src/game-engine/net/inbound-packets/item-on-item-packet.js rename to src/engine/net/inbound-packets/item-on-item.packet.ts index 697c3fdda..22965db72 100644 --- a/src/game-engine/net/inbound-packets/item-on-item-packet.js +++ b/src/engine/net/inbound-packets/item-on-item.packet.ts @@ -1,7 +1,9 @@ -import { logger } from '@runejs/core'; -import { widgets } from '../../config'; +import { logger } from '@runejs/common'; +import { widgets } from '@engine/config'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; -const itemOnItemPacket = (player, packet) => { +const itemOnItemPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; const usedWithItemId = buffer.get('short', 'u', 'le'); const usedWithSlot = buffer.get('short', 'u', 'le'); @@ -28,7 +30,8 @@ const itemOnItemPacket = (player, packet) => { return; } - player.actionPipeline.call('item_on_item', player, usedItem, usedSlot, usedWidgetId, usedWithItem, usedWithSlot, usedWithWidgetId); + player.actionPipeline.call('item_on_item', + player, usedItem, usedSlot, usedWidgetId, usedWithItem, usedWithSlot, usedWithWidgetId); } else { logger.warn(`Unhandled item on item case using widgets ${usedWidgetId}:${usedContainerId} => ${usedWithWidgetId}:${usedWithContainerId}`); } diff --git a/src/game-engine/net/inbound-packets/item-on-npc-packet.ts b/src/engine/net/inbound-packets/item-on-npc.packet.ts similarity index 81% rename from src/game-engine/net/inbound-packets/item-on-npc-packet.ts rename to src/engine/net/inbound-packets/item-on-npc.packet.ts index dcbdc4515..681a5fa08 100644 --- a/src/game-engine/net/inbound-packets/item-on-npc-packet.ts +++ b/src/engine/net/inbound-packets/item-on-npc.packet.ts @@ -1,9 +1,10 @@ -import { logger } from '@runejs/core'; -import { world } from '@engine/game-server'; -import { World } from '@engine/world'; +import { logger } from '@runejs/common'; +import { activeWorld, World } from '@engine/world'; import { widgets } from '@engine/config'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; -const itemOnNpcPacket = (player, packet) => { +const itemOnNpcPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; const npcIndex = buffer.get('short', 'u'); const itemId = buffer.get('short', 'u'); @@ -34,7 +35,7 @@ const itemOnNpcPacket = (player, packet) => { return; } - const npc = world.npcList[npcIndex]; + const npc = activeWorld.npcList[npcIndex]; if (!npc) { return; } diff --git a/src/game-engine/net/inbound-packets/item-on-object-packet.js b/src/engine/net/inbound-packets/item-on-object.packet.ts similarity index 67% rename from src/game-engine/net/inbound-packets/item-on-object-packet.js rename to src/engine/net/inbound-packets/item-on-object.packet.ts index afaa3d036..f157db18f 100644 --- a/src/game-engine/net/inbound-packets/item-on-object-packet.js +++ b/src/engine/net/inbound-packets/item-on-object.packet.ts @@ -1,10 +1,12 @@ -import { logger } from '@runejs/core'; -import { Position } from '../../world/position'; -import { filestore, world } from '../../game-server'; -import { widgets } from '../../config'; -import { getVarbitMorphIndex } from "../../util/varbits"; +import { logger } from '@runejs/common'; +import { filestore } from '@server/game/game-server'; +import { Position, activeWorld } from '@engine/world'; +import { widgets } from '@engine/config'; +import { getVarbitMorphIndex } from '@engine/util'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; -const itemOnObjectPacket = (player, packet) => { +const itemOnObjectPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; const objectY = buffer.get('short', 'u', 'le'); const itemId = buffer.get('short', 'u'); @@ -35,22 +37,25 @@ const itemOnObjectPacket = (player, packet) => { const level = player.position.level; const objectPosition = new Position(objectX, objectY, level); - const { object: locationObject, cacheOriginal } = world.findObjectAtLocation(player, objectId, objectPosition); + const { object: locationObject, cacheOriginal } = activeWorld.findObjectAtLocation(player, objectId, objectPosition); if(!locationObject) { return; } let objectConfig = filestore.configStore.objectStore.getObject(objectId); - if (objectConfig.configChangeDest) { + + if (!objectConfig) { + logger.error(`Could not find object config for object id ${objectId}!`); + } else if (objectConfig.configChangeDest) { let morphIndex = -1; if(objectConfig.varbitId === -1) { if(objectConfig.configId !== -1) { - const configValue = player.metadata['configs'] && player.metadata['configs'][objectConfig.configId] ? player.metadata['configs'][objectConfig.configId] : 0; + const configValue = player.metadata.configs && player.metadata.configs[objectConfig.configId] ? player.metadata.configs[objectConfig.configId] : 0; morphIndex = configValue; } } else { - morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata['configs']); + morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata.configs); } if(morphIndex !== -1) { objectConfig = filestore.configStore.objectStore.getObject(objectConfig.configChangeDest[morphIndex]); diff --git a/src/game-engine/net/inbound-packets/item-on-player-packet.ts b/src/engine/net/inbound-packets/item-on-player.packet.ts similarity index 80% rename from src/game-engine/net/inbound-packets/item-on-player-packet.ts rename to src/engine/net/inbound-packets/item-on-player.packet.ts index d5beb76f4..a1f557e0f 100644 --- a/src/game-engine/net/inbound-packets/item-on-player-packet.ts +++ b/src/engine/net/inbound-packets/item-on-player.packet.ts @@ -1,9 +1,8 @@ -import { logger } from '@runejs/core'; -import { world } from '../../game-server'; -import { World } from '../../world'; -import { widgets } from '../../config'; -import { Player } from '@engine/world/actor/player/player'; -import { PacketData } from '@engine/net/inbound-packets'; +import { logger } from '@runejs/common'; +import { activeWorld, World } from '@engine/world'; +import { widgets } from '@engine/config'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; const itemOnPlayerPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; @@ -37,7 +36,7 @@ const itemOnPlayerPacket = (player: Player, packet: PacketData) => { return; } - const otherPlayer = world.playerList[playerIndex]; + const otherPlayer = activeWorld.playerList[playerIndex]; if(!otherPlayer) { return; } diff --git a/src/engine/net/inbound-packets/item-on-world-item.packet.ts b/src/engine/net/inbound-packets/item-on-world-item.packet.ts new file mode 100644 index 000000000..f3c16b8bc --- /dev/null +++ b/src/engine/net/inbound-packets/item-on-world-item.packet.ts @@ -0,0 +1,60 @@ +import { logger } from '@runejs/common'; +import { widgets } from '@engine/config'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; +import { Position } from '@engine/world'; + +/** + * Parses the item on world item packet and calls the `item_on_world_item` action pipeline. + * + * This will check that the item being used is in the player's inventory, and that the world item exists in the correct location. + * The action pipeline will not be called if either of these conditions are not met. + * + * @param player The player that sent the packet. + * @param packet The packet to parse. + * + * @author jameskmonger + */ +const itemOnWorldItemPacket = (player: Player, packet: PacketData) => { + const { buffer } = packet; + + const usedWithX = buffer.get('short', 'u'); + const usedSlot = buffer.get('short', 'u'); + const usedWithItemId = buffer.get('short', 'u'); + const usedContainerId = buffer.get('short', 's', 'be'); + const usedWidgetId = buffer.get('short', 's', 'be'); + const usedWithY = buffer.get('short', 'u', 'le'); + const usedItemId = buffer.get('short', 'u', 'le'); + + const position = new Position(usedWithX, usedWithY, player.position.level); + + if(usedWidgetId === widgets.inventory.widgetId && usedContainerId === widgets.inventory.containerId) { + // TODO (James) we should use constants for these rather than magic numbers + if(usedSlot < 0 || usedSlot > 27) { + return; + } + + const usedItem = player.inventory.items[usedSlot]; + const usedWithItem = player.instance.getTileModifications(position).mods.worldItems.find(p => p.itemId === usedWithItemId); + if(!usedItem || !usedWithItem) { + logger.warn(`Unhandled item on world item case (A) for ${usedSlot} (${usedItemId}) on ${usedWithItemId} (${usedWithX}, ${usedWithY}) by ${player.username}`); + return; + } + + if(usedItem.itemId !== usedItemId || usedWithItem.itemId !== usedWithItemId) { + logger.warn(`Unhandled item on world item case (B) for ${usedItem.itemId}:${usedItemId} on ${usedWithItem.itemId}:${usedWithItemId} by ${player.username}`); + return; + } + + player.actionPipeline.call('item_on_world_item', player, usedItem, usedWithItem, usedWidgetId, usedContainerId, usedSlot); + } else { + logger.warn(`Unhandled item on world item case (C) using widgets ${usedWidgetId}:${usedContainerId} by ${player.username}`); + } + +}; + +export default { + opcode: 172, + size: 14, + handler: itemOnWorldItemPacket +}; diff --git a/src/game-engine/net/inbound-packets/item-swap-packet.js b/src/engine/net/inbound-packets/item-swap.packet.ts similarity index 76% rename from src/game-engine/net/inbound-packets/item-swap-packet.js rename to src/engine/net/inbound-packets/item-swap.packet.ts index 72433ae7a..255d2aa5f 100644 --- a/src/game-engine/net/inbound-packets/item-swap-packet.js +++ b/src/engine/net/inbound-packets/item-swap.packet.ts @@ -1,6 +1,9 @@ -const itemSwapPacket = (player, packet) => { +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +const itemSwapPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; - const swapType = buffer.get(); + const swapType = buffer.get('byte'); const fromSlot = buffer.get('short', 'u'); const toSlot = buffer.get('short', 'u', 'le'); const containerId = buffer.get('short'); diff --git a/src/game-engine/net/inbound-packets/junk-packets.js b/src/engine/net/inbound-packets/junk.packet.ts similarity index 100% rename from src/game-engine/net/inbound-packets/junk-packets.js rename to src/engine/net/inbound-packets/junk.packet.ts diff --git a/src/game-engine/net/inbound-packets/magic-attack-packet.ts b/src/engine/net/inbound-packets/magic-attack.packet.ts similarity index 54% rename from src/game-engine/net/inbound-packets/magic-attack-packet.ts rename to src/engine/net/inbound-packets/magic-attack.packet.ts index 8e929ae1d..eb199efc1 100644 --- a/src/game-engine/net/inbound-packets/magic-attack-packet.ts +++ b/src/engine/net/inbound-packets/magic-attack.packet.ts @@ -1,17 +1,15 @@ -import { Player, playerOptions } from '../../world/actor/player/player'; -import { world } from '../../game-server'; -import { World } from '../../world'; -import { logger } from '@runejs/core'; -import { PacketData } from '../inbound-packets'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; +import { activeWorld } from '@engine/world'; const magicAttackPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; - const npcWorldIndex = buffer.get('short', 'u'); // unsigned short BE - const widgetId = buffer.get('short', 'u', 'le'); // unsigned short LE - const widgetChildId = buffer.get(); // unsigned short LE + const npcWorldIndex = buffer.get('short', 'u'); // unsigned short BE + const widgetId = buffer.get('short', 'u', 'le'); // unsigned short LE + const widgetChildId = buffer.get('byte'); // unsigned short LE - const npc = world.npcList[npcWorldIndex]; + const npc = activeWorld.npcList[npcWorldIndex]; player.actionPipeline.call('magic_on_npc', npc, player, widgetId, widgetChildId); }; diff --git a/src/game-engine/net/inbound-packets/npc-interaction-packet.ts b/src/engine/net/inbound-packets/npc-interaction.packet.ts similarity index 81% rename from src/game-engine/net/inbound-packets/npc-interaction-packet.ts rename to src/engine/net/inbound-packets/npc-interaction.packet.ts index b5380a165..c5218a9ca 100644 --- a/src/game-engine/net/inbound-packets/npc-interaction-packet.ts +++ b/src/engine/net/inbound-packets/npc-interaction.packet.ts @@ -1,26 +1,26 @@ -import { world } from '@engine/game-server'; -import { World } from '@engine/world'; -import { logger } from '@runejs/core'; -import { Player } from '@engine/world/actor/player/player'; -import { PacketData } from '@engine/net/inbound-packets'; +import { logger } from '@runejs/common'; + +import { PacketData } from '@engine/net'; +import { activeWorld, World } from '@engine/world'; +import { Player } from '@engine/world/actor'; const npcInteractionPacket = (player: Player, packet: PacketData) => { const { buffer, packetId } = packet; - const args = { - 63: [ 'short', 'u', 'le' ], - 116: [ 'short', 'u', 'le' ], - 57: [ 'short', 'u' ], + const packetReaders: Record number> = { + 63: () => buffer.get('short', 'u', 'le'), + 116: () => buffer.get('short', 'u', 'le'), + 57: () => buffer.get('short', 'u'), /*42: 'readUnsignedShortLE', 8: 'readUnsignedShortLE'*/ }; - const npcIndex = buffer.get(...args[packetId]); + const npcIndex = packetReaders[packetId](); if (npcIndex < 0 || npcIndex > World.MAX_NPCS - 1) { return; } - const npc = world.npcList[npcIndex]; + const npc = activeWorld.npcList[npcIndex]; if (!npc) { return; } diff --git a/src/engine/net/inbound-packets/number-input.packet.ts b/src/engine/net/inbound-packets/number-input.packet.ts new file mode 100644 index 000000000..b224785c5 --- /dev/null +++ b/src/engine/net/inbound-packets/number-input.packet.ts @@ -0,0 +1,9 @@ +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +export default { + opcode: 238, + size: 4, + handler: (player: Player, packet: PacketData) => + player.numericInputEvent.next(packet.buffer.get('int', 'u')) +}; diff --git a/src/game-engine/net/inbound-packets/object-interaction-packet.ts b/src/engine/net/inbound-packets/object-interaction.packet.ts similarity index 79% rename from src/game-engine/net/inbound-packets/object-interaction-packet.ts rename to src/engine/net/inbound-packets/object-interaction.packet.ts index 6088a24d6..0351371cc 100644 --- a/src/game-engine/net/inbound-packets/object-interaction-packet.ts +++ b/src/engine/net/inbound-packets/object-interaction.packet.ts @@ -1,10 +1,10 @@ -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; -import { filestore, world } from '@engine/game-server'; -import { Position } from '@engine/world/position'; -import { getVarbitMorphIndex } from '@engine/util/varbits'; -import { PacketData } from '@engine/net/inbound-packets'; -import { Player, Rights } from '@engine/world/actor/player/player'; +import { filestore } from '@server/game/game-server'; +import { PacketData } from '@engine/net'; +import { getVarbitMorphIndex } from '@engine/util'; +import { Position, activeWorld } from '@engine/world'; +import { Player, Rights } from '@engine/world/actor'; interface ObjectInteractionData { @@ -72,7 +72,7 @@ const objectInteractionPacket = (player: Player, packet: PacketData) => { const { objectId, x, y } = objectInteractionPackets[packetId].packetDef(packet); const level = player.position.level; const objectPosition = new Position(x, y, level); - const { object: landscapeObject, cacheOriginal } = world.findObjectAtLocation(player, objectId, objectPosition); + const { object: landscapeObject, cacheOriginal } = activeWorld.findObjectAtLocation(player, objectId, objectPosition); if(!landscapeObject) { if(player.rights === Rights.ADMIN) { player.sendMessage(`Custom object ${objectId} @[${objectPosition.key}]`); @@ -81,21 +81,32 @@ const objectInteractionPacket = (player: Player, packet: PacketData) => { } let objectConfig = filestore.configStore.objectStore.getObject(objectId); + + if (!objectConfig) { + logger.error(`[object-interaction] Could not find object config for object id ${objectId}!`); + return; + } + if (objectConfig.configChangeDest) { let morphIndex = -1; if(objectConfig.varbitId === -1) { if(objectConfig.configId !== -1) { - morphIndex = player.metadata['configs'] && player.metadata['configs'][objectConfig.configId] ? - player.metadata['configs'][objectConfig.configId] : 0; + morphIndex = player.metadata.configs && player.metadata.configs[objectConfig.configId] ? + player.metadata.configs[objectConfig.configId] : 0; } } else { - morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata['configs']); + morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata.configs); } if(morphIndex !== -1) { objectConfig = filestore.configStore.objectStore.getObject(objectConfig.configChangeDest[morphIndex]); } } + if (!objectConfig) { + logger.error(`[object-interaction - after morph] Could not find object config for object id ${objectId}!`); + return; + } + const actionIdx = objectInteractionPackets[packetId].index; let optionName = `action-${actionIdx + 1}`; if(objectConfig.options && objectConfig.options.length >= actionIdx) { diff --git a/src/game-engine/net/inbound-packets/pickup-item-packet.js b/src/engine/net/inbound-packets/pickup-item.packet.ts similarity index 84% rename from src/game-engine/net/inbound-packets/pickup-item-packet.js rename to src/engine/net/inbound-packets/pickup-item.packet.ts index 5045386d9..0633542cf 100644 --- a/src/game-engine/net/inbound-packets/pickup-item-packet.js +++ b/src/engine/net/inbound-packets/pickup-item.packet.ts @@ -1,6 +1,8 @@ -import { Position } from '../../world/position'; +import { Position } from '@engine/world'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; -const pickupItemPacket = (player, packet) => { +const pickupItemPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; const y = buffer.get('short', 'u'); const itemId = buffer.get('short', 'u'); diff --git a/src/game-engine/net/inbound-packets/player-interaction-packet.js b/src/engine/net/inbound-packets/player-interaction.packet.ts similarity index 63% rename from src/game-engine/net/inbound-packets/player-interaction-packet.js rename to src/engine/net/inbound-packets/player-interaction.packet.ts index 35242e06d..c8b7b28b0 100644 --- a/src/game-engine/net/inbound-packets/player-interaction-packet.js +++ b/src/engine/net/inbound-packets/player-interaction.packet.ts @@ -1,21 +1,24 @@ -import { playerOptions } from '../../world/actor/player/player'; -import { world } from '../../game-server'; -import { World } from '../../world'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; -const playerInteractionPacket = (player, packet) => { +import { activeWorld, World } from '@engine/world'; +import { Player, playerOptions } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +const playerInteractionPacket = (player: Player, packet: PacketData) => { const { buffer, packetId } = packet; - const args = { - 68: [ 'short', 'u', 'le' ], - 211: [ 'short', 'u', 'le' ] + + const packetReaders: Record number> = { + 68: () => buffer.get('short', 'u', 'le'), + 211: () => buffer.get('short', 'u', 'le'), }; - const playerIndex = buffer.get(...args[packetId]) - 1; + + const playerIndex = packetReaders[packetId]() - 1; if(playerIndex < 0 || playerIndex > World.MAX_PLAYERS - 1) { return; } - const otherPlayer = world.playerList[playerIndex]; + const otherPlayer = activeWorld.playerList[playerIndex]; if(!otherPlayer) { return; } diff --git a/src/game-engine/net/inbound-packets/private-message-packet.js b/src/engine/net/inbound-packets/private-message.packet.ts similarity index 59% rename from src/game-engine/net/inbound-packets/private-message-packet.js rename to src/engine/net/inbound-packets/private-message.packet.ts index 9a66150be..297843430 100644 --- a/src/game-engine/net/inbound-packets/private-message-packet.js +++ b/src/engine/net/inbound-packets/private-message.packet.ts @@ -1,14 +1,16 @@ -import { longToString } from '../../util/strings'; -import { world } from '../../game-server'; +import { longToString } from '@engine/util'; +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; +import { activeWorld } from '@engine/world'; export default { opcode: 207, size: -3, - handler: (player, packet) => { + handler: (player: Player, packet: PacketData) => { const { buffer } = packet; buffer.get('byte'); // junk - const nameLong = buffer.get('long'); + const nameLong = BigInt(buffer.get('long')); const username = longToString(nameLong).toLowerCase(); const messageLength = buffer.length - 9; const messageBytes = new Array(messageLength); @@ -16,7 +18,7 @@ export default { messageBytes[i] = buffer[buffer.readerIndex + i]; } - const otherPlayer = world.findActivePlayerByUsername(username); + const otherPlayer = activeWorld.findActivePlayerByUsername(username); if(otherPlayer) { otherPlayer.privateMessageReceived(player, messageBytes); } diff --git a/src/engine/net/inbound-packets/remove-friend.packet.ts b/src/engine/net/inbound-packets/remove-friend.packet.ts new file mode 100644 index 000000000..be8a92c8a --- /dev/null +++ b/src/engine/net/inbound-packets/remove-friend.packet.ts @@ -0,0 +1,17 @@ +import { longToString } from '@engine/util'; +import { Player, PrivateMessaging } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +export default { + opcode: 255, + size: 8, + handler: (player: Player, packet: PacketData) => { + const friendName = longToString(BigInt(packet.buffer.get('long'))); + if(!friendName) { + return; + } + + player.removeFriend(friendName); + PrivateMessaging.friendRemoved(player, friendName); + } +}; diff --git a/src/engine/net/inbound-packets/social-button.packet.ts b/src/engine/net/inbound-packets/social-button.packet.ts new file mode 100644 index 000000000..66a6e1cf6 --- /dev/null +++ b/src/engine/net/inbound-packets/social-button.packet.ts @@ -0,0 +1,20 @@ +import { Player, PrivateMessaging } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +export default { + opcode: 32, + size: 3, + handler: (player: Player, packet: PacketData) => { + const { buffer } = packet; + + const currentPrivateChatMode = player.settings.privateChatMode; + + player.settings.publicChatMode = buffer.get('byte'); + player.settings.privateChatMode = buffer.get('byte'); + player.settings.tradeMode = buffer.get('byte'); + + if(currentPrivateChatMode !== player.settings.privateChatMode) { + PrivateMessaging.playerPrivateChatModeChanged(player); + } + } +}; diff --git a/src/game-engine/net/inbound-packets/walk-packet.js b/src/engine/net/inbound-packets/walk.packet.ts similarity index 67% rename from src/game-engine/net/inbound-packets/walk-packet.js rename to src/engine/net/inbound-packets/walk.packet.ts index ffba42094..756eddb67 100644 --- a/src/game-engine/net/inbound-packets/walk-packet.js +++ b/src/engine/net/inbound-packets/walk.packet.ts @@ -1,4 +1,7 @@ -const walkPacket = (player, packet) => { +import { Player } from '@engine/world/actor'; +import { PacketData } from '@engine/net'; + +const walkPacket = (player: Player, packet: PacketData) => { const { buffer, packetSize, packetId } = packet; let size = packetSize; @@ -9,20 +12,24 @@ const walkPacket = (player, packet) => { const totalSteps = Math.floor((size - 5) / 2); const firstY = buffer.get('short', 'u', 'le'); - const runSteps = buffer.get() === 1; // @TODO forced running + const runSteps = buffer.get('byte') === 1; // @TODO forced running const firstX = buffer.get('short', 'u', 'le'); const walkingQueue = player.walkingQueue; player.actionsCancelled.next('manual-movement'); - player.walkingTo = null; + + if(player.metadata.walkingTo) { + delete player.metadata.walkingTo; + } + walkingQueue.clear(); walkingQueue.valid = true; walkingQueue.add(firstX, firstY); for(let i = 0; i < totalSteps; i++) { - const x = buffer.get(); - const y = buffer.get(); + const x = buffer.get('byte'); + const y = buffer.get('byte'); walkingQueue.add(x + firstX, y + firstY); } }; diff --git a/src/game-engine/net/inbound-packets/widget-interaction-packet.ts b/src/engine/net/inbound-packets/widget-interaction.packet.ts similarity index 78% rename from src/game-engine/net/inbound-packets/widget-interaction-packet.ts rename to src/engine/net/inbound-packets/widget-interaction.packet.ts index 7166e4365..80f9eb925 100644 --- a/src/game-engine/net/inbound-packets/widget-interaction-packet.ts +++ b/src/engine/net/inbound-packets/widget-interaction.packet.ts @@ -1,6 +1,5 @@ -import { Player } from '@engine/world/actor/player/player'; -import { PacketData } from '@engine/net/inbound-packets'; - +import { PacketData } from '@engine/net'; +import { Player } from '@engine/world/actor'; const widgetInteractionPacket = (player: Player, packet: PacketData) => { const { buffer } = packet; diff --git a/src/engine/net/inbound-packets/widgets-closed-packet.ts b/src/engine/net/inbound-packets/widgets-closed-packet.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/game-engine/net/inbound-packets/widgets-closed-packet.js b/src/engine/net/inbound-packets/widgets-closed.packet.ts similarity index 100% rename from src/game-engine/net/inbound-packets/widgets-closed-packet.js rename to src/engine/net/inbound-packets/widgets-closed.packet.ts diff --git a/src/engine/net/index.ts b/src/engine/net/index.ts new file mode 100644 index 000000000..ba952fe7e --- /dev/null +++ b/src/engine/net/index.ts @@ -0,0 +1,4 @@ +export * from './inbound-packet-handler'; +export * from './isaac'; +export * from './outbound-packet-handler'; +export * from './packet'; diff --git a/src/game-engine/net/isaac.ts b/src/engine/net/isaac.ts similarity index 99% rename from src/game-engine/net/isaac.ts rename to src/engine/net/isaac.ts index 8a667d1a2..df9cd0dc1 100644 --- a/src/game-engine/net/isaac.ts +++ b/src/engine/net/isaac.ts @@ -7,7 +7,7 @@ export class Isaac { private r: number[] = Array(256); // result array private gnt = 0; // generation counter - public constructor(seed?: number[]) { + public constructor(seed: number[]) { this.seed(seed); } diff --git a/src/game-engine/net/outbound-packets.ts b/src/engine/net/outbound-packet-handler.ts similarity index 93% rename from src/game-engine/net/outbound-packets.ts rename to src/engine/net/outbound-packet-handler.ts index 670d14e3e..13b4c8957 100644 --- a/src/game-engine/net/outbound-packets.ts +++ b/src/engine/net/outbound-packet-handler.ts @@ -1,25 +1,23 @@ -import { Player, SidebarTab } from '../world/actor/player/player'; import { Socket } from 'net'; -import { Packet, PacketType } from '@engine/net/packet'; -import { ItemContainer } from '@engine/world/items/item-container'; -import { Item } from '@engine/world/items/item'; -import { Position } from '@engine/world/position'; -import { Chunk, ChunkUpdateItem } from '@engine/world/map/chunk'; -import { WorldItem } from '@engine/world/items/world-item'; -import { ByteBuffer } from '@runejs/core/buffer'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { stringToLong } from '@engine/util/strings'; import { LandscapeObject } from '@runejs/filestore'; +import { ByteBuffer, logger } from '@runejs/common'; + +import { serverConfig } from '@server/game'; +import { Packet, PacketType } from '@engine/net'; import { xteaRegions } from '@engine/config'; -import { world } from '@engine/game-server'; -import { ConstructedChunk, ConstructedRegion } from '@engine/world/map/region'; +import { activeWorld } from '@engine/world'; +import { stringToLong } from '@engine/util'; +import { ChunkUpdateItem, Position } from '@engine/world'; +import { Player, SidebarTab, Npc } from '@engine/world/actor'; +import { ItemContainer, Item, WorldItem } from '@engine/world/items'; +import { Chunk, ConstructedChunk, ConstructedRegion } from '@engine/world/map'; /** * A helper class for sending various network packets back to the game client. */ -export class OutboundPackets { +export class OutboundPacketHandler { private static privateMessageCounter: number = Math.floor(Math.random() * 100000000); @@ -63,7 +61,7 @@ export class OutboundPackets { const packet = new Packet(51, PacketType.DYNAMIC_SMALL); packet.put(stringToLong(sender.username.toLowerCase()), 'LONG'); packet.put(32767, 'SHORT'); - packet.put(OutboundPackets.privateMessageCounter++, 'INT24'); + packet.put(OutboundPacketHandler.privateMessageCounter++, 'INT24'); packet.put(sender.rights); packet.putBytes(Buffer.from(message)); this.queue(packet); @@ -73,7 +71,7 @@ export class OutboundPackets { public sendProjectile(position: Position, offsetX: number, offsetY: number, id: number, startHeight: number, endHeight: number, speed: number, lockon: number, delay: number) { this.updateReferencePosition(position); - + const packet = new Packet(1); packet.put(0); packet.put(offsetY, 'byte'); @@ -87,7 +85,8 @@ export class OutboundPackets { packet.put(16); packet.put(64); this.queue(packet); - } + } + public updateFriendStatus(friendName: string, worldId: number): void { const packet = new Packet(156); packet.put(stringToLong(friendName.toLowerCase()), 'LONG'); @@ -159,6 +158,11 @@ export class OutboundPackets { packet.put(offset, 'BYTE'); } } else if(update.type === 'REMOVE') { + if (!update.object) { + logger.warn('Tried to remove object that does not exist.'); + return; + } + const offset = this.getChunkPositionOffset(update.object.x, update.object.y, chunk); packet.put(143, 'BYTE'); packet.put(offset); @@ -280,8 +284,8 @@ export class OutboundPackets { public updateClientConfig(configId: number, value: number): void { let packet: Packet; const metadata = this.player.metadata; - if(!metadata['configs']) { - metadata['configs'] = [] + if(!metadata.configs) { + metadata.configs = [] } metadata.configs[configId] = value; @@ -318,7 +322,9 @@ export class OutboundPackets { public updateWidgetItemModel(widgetId: number, itemId: number, scale?: number): void { const packet = new Packet(21); - packet.put(scale, 'SHORT'); + + // TODO (Jameskmonger) what should the default value of `scale` be? + packet.put(scale || 0, 'SHORT'); packet.put(itemId, 'SHORT', 'LITTLE_ENDIAN'); packet.put(widgetId, 'SHORT', 'LITTLE_ENDIAN'); @@ -358,7 +364,7 @@ export class OutboundPackets { } // @TODO this can support multiple items/slots !!! - public sendUpdateSingleWidgetItem(widget: { widgetId: number, containerId: number }, slot: number, item: Item): void { + public sendUpdateSingleWidgetItem(widget: { widgetId: number, containerId: number }, slot: number, item: Item | null): void { const packet = new Packet(214, PacketType.DYNAMIC_LARGE); packet.put(widget.widgetId << 16 | widget.containerId, 'INT'); packet.put(slot, 'SMART'); @@ -452,10 +458,6 @@ export class OutboundPackets { } public sendTabWidget(tabIndex: SidebarTab, widgetId: number | null): void { - if(widgetId < 0) { - return; - } - const packet = new Packet(140); packet.put(widgetId === null || widgetId === -1 ? 65535 : widgetId, 'SHORT'); packet.put(tabIndex); @@ -600,8 +602,8 @@ export class OutboundPackets { const mapWorldX = mapData.renderPosition.x; const mapWorldY = mapData.renderPosition.y; - const topCornerMapChunk = world.chunkManager.getChunkForWorldPosition(new Position(mapWorldX, mapWorldY, this.player.position.level)); - const playerChunk = world.chunkManager.getChunkForWorldPosition(this.player.position); + const topCornerMapChunk = activeWorld.chunkManager.getChunkForWorldPosition(new Position(mapWorldX, mapWorldY, this.player.position.level)); + const playerChunk = activeWorld.chunkManager.getChunkForWorldPosition(this.player.position); const offsetX = playerChunk.position.x - (topCornerMapChunk.position.x - 2); const offsetY = playerChunk.position.y - (topCornerMapChunk.position.y - 2); @@ -643,12 +645,14 @@ export class OutboundPackets { packet.closeBitBuffer(); + const encryptionEnabled = serverConfig.encryptionEnabled === undefined ? true : serverConfig.encryptionEnabled; + // Put the xtea keys for the two construction room template maps // Map coords: 29,79 && 30,79 for(let mapX = 29; mapX <= 30; mapX++) { const xteaRegion = xteaRegions[`l${mapX}_79`]; for(let seeds = 0; seeds < 4; seeds++) { - packet.put(xteaRegion?.key[seeds] || 0, 'int'); + packet.put(encryptionEnabled ? (xteaRegion?.key[seeds] ?? 0) : 0, 'int'); } } @@ -668,11 +672,13 @@ export class OutboundPackets { const startY = Math.floor(this.player.position.chunkY / 8); const endY = Math.floor((this.player.position.chunkY + 12) / 8); + const encryptionEnabled = serverConfig.encryptionEnabled === undefined ? true : serverConfig.encryptionEnabled; + for(let mapX = startX; mapX <= endX; mapX++) { for(let mapY = startY; mapY <= endY; mapY++) { const xteaRegion = xteaRegions[`l${mapX}_${mapY}`]; for(let seeds = 0; seeds < 4; seeds++) { - packet.put(xteaRegion?.key[seeds] || 0, 'int'); + packet.put(encryptionEnabled ? (xteaRegion?.key[seeds] ?? 0) : 0, 'int'); } } } diff --git a/src/game-engine/net/packet.ts b/src/engine/net/packet.ts similarity index 97% rename from src/game-engine/net/packet.ts rename to src/engine/net/packet.ts index 00fd0dea4..abd649aa8 100644 --- a/src/game-engine/net/packet.ts +++ b/src/engine/net/packet.ts @@ -1,5 +1,5 @@ import { Isaac } from './isaac'; -import { ByteBuffer } from '@runejs/core/buffer'; +import { ByteBuffer } from '@runejs/common'; /** * The type of packet; Fixed, Dynamic Small (sized byte), or Dynamic Large (sized short) diff --git a/src/game-engine/plugins/content-plugin.ts b/src/engine/plugins/content-plugin.ts similarity index 92% rename from src/game-engine/plugins/content-plugin.ts rename to src/engine/plugins/content-plugin.ts index c4e450bbc..d4a4b6bc6 100644 --- a/src/game-engine/plugins/content-plugin.ts +++ b/src/engine/plugins/content-plugin.ts @@ -1,8 +1,8 @@ -import { logger } from '@runejs/core'; -import { getFiles } from '@runejs/core/fs'; +import { logger } from '@runejs/common'; +import { getFiles } from '@runejs/common/fs'; import { join } from 'path'; -import { ActionHook } from '@engine/world/action/hooks'; +import { ActionHook } from '@engine/action/hook'; import { Quest } from '@engine/world/actor/player/quest'; diff --git a/src/engine/plugins/index.ts b/src/engine/plugins/index.ts new file mode 100644 index 000000000..a0013b5ee --- /dev/null +++ b/src/engine/plugins/index.ts @@ -0,0 +1,3 @@ +export * from './content-plugin'; +export * from './loader'; +export * from './util'; diff --git a/src/engine/plugins/loader.ts b/src/engine/plugins/loader.ts new file mode 100644 index 000000000..f1f81b79d --- /dev/null +++ b/src/engine/plugins/loader.ts @@ -0,0 +1,75 @@ +import { loadPluginFiles } from '@engine/plugins/content-plugin'; +import { Quest } from '@engine/world/actor'; +import { logger } from '@runejs/common'; +import { ActionHook, ActionType, sortActionHooks } from '@engine/action'; + +/** + * A type for describing the plugin action hook map. + */ +type PluginActionHookMap = { + [key in ActionType]?: ActionHook[]; +}; + +/** + * A type for describing the plugin action hook map. + */ +interface PluginQuestMap { + [key: string]: Quest; +} + +/** + * A list of action hooks imported from content plugins. + */ +export let actionHookMap: PluginActionHookMap = {}; +/** + * A list of quests imported from content plugins. + */ +export let questMap: PluginQuestMap = {}; + +/** + * Searches for and loads all plugin files and their associated action hooks. + */ +export async function loadPlugins(): Promise { + actionHookMap = {}; + questMap = {}; + const plugins = await loadPluginFiles(); + + const pluginActionHookList = plugins?.filter(plugin => !!plugin?.hooks)?.map(plugin => plugin.hooks); + + if(pluginActionHookList && pluginActionHookList.length !== 0) { + pluginActionHookList.reduce( + (a, b) => (a || []).concat(b || []))?.forEach(action => { + if(!(action instanceof Quest)) { + if(!actionHookMap[action.type]) { + actionHookMap[action.type] = []; + } + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + actionHookMap[action.type]!.push(action); + } else { + if(!actionHookMap['quest']) { + actionHookMap['quest'] = []; + } + + actionHookMap['quest'].push(action); + } + }); + } else { + logger.warn(`No action hooks detected - update plugins.`); + } + + for (const plugin of plugins) { + if (!plugin.quests) { + continue; + } + + for (const quest of plugin.quests) { + questMap[quest.id] = quest; + } + } + + // @TODO implement proper sorting rules + Object.keys(actionHookMap) + .forEach(key => actionHookMap[key] = + sortActionHooks(actionHookMap[key])); +} diff --git a/src/engine/plugins/reload-content.ts b/src/engine/plugins/reload-content.ts new file mode 100644 index 000000000..ed5020206 --- /dev/null +++ b/src/engine/plugins/reload-content.ts @@ -0,0 +1,96 @@ +import { sep } from 'path'; +import { loadGameConfigurations } from '@engine/config'; +import { loadPackets } from '@engine/net'; +import { loadPlugins } from '@engine/plugins/loader'; +import { logger } from '@runejs/common'; +import { Player } from '@engine/world/actor'; + + +export const reloadContentCommands = [ + 'plugins', 'reload', 'content', 'hotload', 'refresh', 'restart', 'r' +]; + +export const reloadContent = async (player: Player, isConsole: boolean = false) => { + player.sendLogMessage(' ', isConsole); + player.sendLogMessage('Deleting content cache...', isConsole); + + const includeList = [ + 'plugins' + ].map(p => sep + p + sep); + + const ignoreList = [ + 'node_modules', + 'engine', + 'server' + ].map(p => sep + p + sep); + + const pluginCache: string[] = []; + const cacheKeys = Object.keys(require.cache); + + // Delete node cache for all the old JS plugins + cacheLoop: + for (const cacheKey of cacheKeys) { + const cachedItem = require.cache[cacheKey]; + + if (!cachedItem) { + continue; + } + + const path = typeof cachedItem === 'string' ? cachedItem : cachedItem?.path; + + if (!path) { + continue; + } + + for (const ignoreItem of ignoreList) { + if (path.indexOf(ignoreItem) !== -1) { + continue cacheLoop; + } + } + + let includePath = false; + + for (const includeItem of includeList) { + if (path.indexOf(includeItem) !== -1) { + includePath = true; + break; + } + } + + if (includePath) { + pluginCache.push(cacheKey); + } + } + + console.log(pluginCache); + + for (const key of pluginCache) { + delete require.cache[require.resolve(key)]; + } + + try { + player.sendLogMessage('Reloading plugins...', isConsole); + await loadPlugins(); + } catch (error) { + player.sendLogMessage('Error reloading content.', isConsole); + logger.error(error); + } + + try { + player.sendLogMessage('Reloading configurations...', isConsole); + await loadGameConfigurations(); + } catch (error) { + player.sendLogMessage('Error reloading configurations.', isConsole); + logger.error(error); + } + + try { + player.sendLogMessage('Reloading packets...', isConsole); + await loadPackets(); + } catch (error) { + player.sendLogMessage('Error reloading packets.', isConsole); + logger.error(error); + } + + player.sendLogMessage('Reload completed.', isConsole); +}; diff --git a/src/engine/plugins/util.ts b/src/engine/plugins/util.ts new file mode 100644 index 000000000..a0ccaa14c --- /dev/null +++ b/src/engine/plugins/util.ts @@ -0,0 +1,110 @@ +import { Npc, Player } from '@engine/world/actor'; +import { Subject, timer } from 'rxjs'; +import { Position, World } from '@engine/world'; +import { LandscapeObject } from '@runejs/filestore'; + +/** + * A type of action that loops until either one of three things happens: + * 1. A player is specified within `options` who's `actionsCancelled` event has been fired during the loop. + * 2. An npc is specified within `options` who no longer exists at some point during the loop. + * 3. The `cancel()` function is manually called, presumably when the purpose of the loop has been completed. + * @param options Options to provide to the looping action, which include: + * `ticks` the number of game ticks between loop cycles. Defaults to 1 game tick between loops. + * `delayTicks` the number of game ticks to wait before starting the first loop. Defaults to 0 game ticks. + * `player` the player that the loop belongs to. Providing this field will cause the loop to cancel if this + * player's `actionsCancelled` is fired during the loop. + * `npc` the npc that the loop belongs to. This will Providing this field will cause the loop to cancel if + * this npc is flagged to no longer exist during the loop. + * @deprecated - use new Action Hook task system instead. + */ +export const loopingEvent = (options?: { + ticks?: number; + delayTicks?: number; + npc?: Npc; + player?: Player; +}): { event: Subject, cancel: () => void } => { + if(!options) { + options = {}; + } + + const { ticks, delayTicks, npc, player } = options; + const event: Subject = new Subject(); + + const subscription = timer(delayTicks === undefined ? 0 : (delayTicks * World.TICK_LENGTH), + ticks === undefined ? World.TICK_LENGTH : (ticks * World.TICK_LENGTH)).subscribe(() => { + if(npc && !npc.exists) { + event.complete(); + subscription.unsubscribe(); + return; + } + + event.next(); + }); + + let actionCancelled; + + if(player) { + actionCancelled = player.actionsCancelled.subscribe(() => { + subscription.unsubscribe(); + actionCancelled.unsubscribe(); + event.complete(); + }); + } + + return { + event, cancel: () => { + subscription.unsubscribe(); + + if(actionCancelled) { + actionCancelled.unsubscribe(); + } + + event.complete(); + } + }; +}; +/** + * A walk-to type of action that requires the specified player to walk to a specific destination before proceeding. + * Note that this does not force the player to walk, it simply checks to see if the player is walking where specified. + * @param player The player that must walk to a specific position. + * @param position The position that the player needs to end up at. + * @param interactingAction [optional] The information about the interaction that the player is making. Not required. + * @deprecated - use methods provided within the Actor API to force or await movement + */ +export const playerWalkTo = async(player: Player, position: Position, interactingAction?: { + interactingObject?: LandscapeObject; +}): Promise => { + return new Promise((resolve, reject) => { + player.metadata.walkingTo = position; + + const inter = setInterval(() => { + if(!player.metadata.walkingTo || !player.metadata.walkingTo.equals(position)) { + reject(); + clearInterval(inter); + return; + } + + if(!player.walkingQueue.moving()) { + if(!interactingAction) { + if(player.position.distanceBetween(position) > 1) { + reject(); + } else { + resolve(); + } + } else { + if(interactingAction.interactingObject) { + const locationObject = interactingAction.interactingObject; + if(player.position.withinInteractionDistance(locationObject)) { + resolve(); + } else { + reject(); + } + } + } + + clearInterval(inter); + player.metadata.walkingTo = undefined; + } + }, 100); + }); +}; diff --git a/src/engine/task/README.md b/src/engine/task/README.md new file mode 100644 index 000000000..092378499 --- /dev/null +++ b/src/engine/task/README.md @@ -0,0 +1,138 @@ +# Task system + +The task system allows you to write content which will be executed on the tick cycles of the server. + +You can configure a task to execute every `n` ticks (minimum of `1` for every tick), and you can also choose a number of other behaviours, such as whether the task should execute immediately or after a delay, as well as set to repeat indefinitely. + +## Scheduling a task + +You can schedule a task by registering it with a `TaskScheduler`. + +The task in the example of below runs with an interval of `2`, i.e. it will be executed every 2 ticks. + +```ts +class MyTask extends Task { + public constructor() { + super({ interval: 2 }); + } + + public execute(): void { + console.log('2 ticks'); + } +} + +const scheduler = new TaskScheduler(); + +scheduler.addTask(new MyTask()); + +scheduler.tick(); +scheduler.tick(); // '2 ticks' +``` + +Every two times that `scheduler.tick()` is called, it will run the `execute` function of your task. + +## Task configuration + +You can pass a `TaskConfig` object to the `Task` constructor in order to configure various aspects of your task. + +### Timing + +The most simple configuration option for a `Task` is the `interval` option. Your task will be executed every `interval` amount of ticks. + +```ts +/** +* The number of ticks between each execution of the task. +*/ +interval: number; +``` + +For example, with an interval of `1`, your task will run every tick. The default value is `1`. + +### Immediate execution + +You can configure your task to execute immediately with the `immediate` option. + +```ts +/** +* Should the task be executed on the first tick after it is added? +*/ +immediate: boolean; +``` + +For example, if `immediate` is `true` and `interval` is `5`, your task will run on the 1st and 6th ticks (and so on). + +### Repeating + +You can use the `repeat` option to tell your task to run forever. + +```ts +/** +* Should the task be repeated indefinitely? +*/ +repeat: boolean; +``` + +You can use `this.stop()` inside the task to stop it from repeating further. + +### Stacking + +The `stackType` and `stackGroup` properties allow you to control how your task interacts with other, similar tasks. + +```ts +/** +* How the task should be stacked with other tasks of the same stack group. +*/ +stackType: TaskStackType; + +/** +* The stack group for this task. +*/ +stackGroup: string; +``` + +When `stackType` is set to `TaskStackType.NEVER`, other tasks with the same `stackGroup` will be stopped when your task is enqueued. A `stackType` of `TaskStackType.STACK` will allow your task to run with others of the same group. + +The default type is `TaskStackType.STACK` and the group is `TaskStackGroup.ACTION` (`'action'`) + +## Task Subtypes + +Rather than extending `Task`, there are a number of subclasses you can extend which will give you some syntactic sugar around common functionality. + +- `ActorTask` + + This is the base task to be performed by an `Actor`. It will automatically listen to the actor's walking queue, and stop the task if it has a `breakType` of `ON_MOVE`. + +- `ActorWalkToTask` + + This task will make an actor walk to a `Position` or `LandscapeObject` and will expose the `atDestination` property for your extended task to query. You can then begin executing your task logic. + +- `ActorLandscapeObjectInteractionTask` + + This task extends `ActorWalkToTask` and will make an actor walk to a given `LandscapeObject`, before exposing the `landscapeObject` property for your task to use. + +- `ActorWorldItemInteractionTask` + + This task extends `ActorWalkToTask` and will make an actor walk to a given `WorldItem`, before exposing the `worldItem` property for your task to use. + +# Future improvements + +- Stalling executions for certain tasks when interface is open + - should we create a `PlayerTask` to contain this behaviour? The `breakType` behaviour could be moved to this base, rather than `ActorTask` + +- Consider refactoring this system to use functional programming patterns. Composition should be favoured over inheritance generally, and there are some examples of future tasks which may be easier if we could compose tasks from building blocks. Consider the implementation of some task which requires both a `LandscapeObject` and a `WorldItem` - we currently would need to create some custom task which borrowed behaviour from the `ActorLandscapeObjectInteractionTask` and `ActorWorldItemInteractionTask`. TypeScript mixins could be useful here. + +# Content requiring conversion to task system + +Highest priority is to convert pieces of content which make use of the old `task` system. These are: + +- Magic attack +- Magic teleports +- Prayer +- Combat +- Forging (smithing) +- Woodcutting + +The following areas will make interesting use of the task system and would serve as a good demonstration: + +- Health regen +- NPC movement diff --git a/src/engine/task/impl/actor-landscape-object-interaction-task.ts b/src/engine/task/impl/actor-landscape-object-interaction-task.ts new file mode 100644 index 000000000..79e9fd522 --- /dev/null +++ b/src/engine/task/impl/actor-landscape-object-interaction-task.ts @@ -0,0 +1,106 @@ +import { LandscapeObject } from '@runejs/filestore'; +import { activeWorld, Position } from '@engine/world'; +import { Actor } from '@engine/world/actor'; +import { ActorWalkToTask } from './actor-walk-to-task'; + +/** + * A task for an actor to interact with a {@link LandscapeObject}. + * + * This task extends {@link ActorWalkToTask} and will walk the actor to the object. + * Once the actor is within range of the object, the task will expose the {@link landscapeObject} property + * + * @author jameskmonger + */ +export abstract class ActorLandscapeObjectInteractionTask extends ActorWalkToTask { + private _landscapeObject: LandscapeObject; + private _objectPosition: Position; + + /** + * Gets the {@link LandscapeObject} that this task is interacting with. + * + * @returns If the object is still present, and the actor is at the destination, the object. + * Otherwise, `null`. + * + * TODO (jameskmonger) unit test this + */ + protected get landscapeObject(): LandscapeObject | null { + // TODO (jameskmonger) consider if we want to do these checks rather than delegating to the child task + // as currently the subclass has to store it in a subclass property if it wants to use it + // without these checks + if (!this.atDestination) { + return null; + } + + if (!this._landscapeObject) { + return null; + } + + return this._landscapeObject; + } + + /** + * Get the position of this task's landscape object + * + * @returns The position of this task's landscape object, or null if the landscape object is not present + */ + protected get landscapeObjectPosition(): Position | null { + if (!this._landscapeObject) { + return null; + } + + return this._objectPosition; + } + + /** + * @param actor The actor executing this task. + * @param landscapeObject The landscape object to interact with. + * @param sizeX The size of the LandscapeObject in the X direction. + * @param sizeY The size of the LandscapeObject in the Y direction. + */ + constructor ( + actor: TActor, + landscapeObject: LandscapeObject, + sizeX: number = 1, + sizeY: number = 1 + ) { + super( + actor, + landscapeObject, + Math.max(sizeX, sizeY) + ); + + if (!landscapeObject) { + this.stop(); + return; + } + + // create the Position here to prevent instantiating a new Position every tick + this._objectPosition = new Position(landscapeObject.x, landscapeObject.y, landscapeObject.level); + this._landscapeObject = landscapeObject; + } + + /** + * Checks for the continued presence of the {@link LandscapeObject} and stops the task if it is no longer present. + * + * TODO (jameskmonger) unit test this + */ + public execute() { + super.execute(); + + if (!this.isActive || !this.atDestination) { + return; + } + + if (!this._landscapeObject) { + this.stop(); + return; + } + + const { object: worldObject } = activeWorld.findObjectAtLocation(this.actor, this._landscapeObject.objectId, this._objectPosition); + + if (!worldObject) { + this.stop(); + return; + } + } +} diff --git a/src/engine/task/impl/actor-task.ts b/src/engine/task/impl/actor-task.ts new file mode 100644 index 000000000..83fb871e8 --- /dev/null +++ b/src/engine/task/impl/actor-task.ts @@ -0,0 +1,65 @@ +import { Subscription } from 'rxjs'; +import { Actor } from '@engine/world/actor'; +import { TaskBreakType, TaskConfig } from '../types'; +import { Task } from '../task'; + +/** + * A task that is executed by an actor. + * + * If the task has a break type of ON_MOVE, the ActorTask will subscribe to the actor's + * movement events and will stop executing when the actor moves. + * + * @author jameskmonger + */ +export abstract class ActorTask extends Task { + /** + * A function that is called when a movement event is queued on the actor. + * + * This will be `null` if the task does not break on movement. + */ + private walkingQueueSubscription: Subscription | null = null; + + /** + * @param actor The actor executing this task. + * @param config The task configuration. + */ + constructor( + protected readonly actor: TActor, + config?: TaskConfig + ) { + super(config); + + this.listenForMovement(); + } + + /** + * Called when the task is stopped and unsubscribes from the actor's walking queue if necessary. + * + * TODO (jameskmonger) unit test this + */ + public onStop(): void { + if (this.walkingQueueSubscription) { + this.walkingQueueSubscription.unsubscribe(); + } + } + + /** + * If required, listen to the actor's walking queue to stop the task + * + * This function uses `setImmediate` to ensure that the subscription to the + * walking queue is not created + * + * TODO (jameskmonger) unit test this + */ + private listenForMovement(): void { + if (!this.breaksOn(TaskBreakType.ON_MOVE)) { + return; + } + + setImmediate(() => { + this.walkingQueueSubscription = this.actor.walkingQueue.movementQueued$.subscribe(() => { + this.stop(); + }); + }); + } +} diff --git a/src/engine/task/impl/actor-walk-to-task.ts b/src/engine/task/impl/actor-walk-to-task.ts new file mode 100644 index 000000000..f56438940 --- /dev/null +++ b/src/engine/task/impl/actor-walk-to-task.ts @@ -0,0 +1,110 @@ +import { LandscapeObject } from '@runejs/filestore'; +import { Position } from '@engine/world/position'; +import { Actor } from '@engine/world/actor'; +import { TaskStackType, TaskBreakType, TaskStackGroup } from '../types'; +import { ActorTask } from './actor-task'; + +/** + * This ActorWalkToTask interface allows us to merge with the ActorWalkToTask class + * and add optional methods to the class. + * + * There is no way to add optional methods directly to an abstract class. + * + * @author jameskmonger + */ +export interface ActorWalkToTask extends ActorTask { + /** + * An optional function that is called when the actor arrives at the destination. + */ + onArrive?(): void; +} + +/** + * An abstract task that will make an Actor walk to a specific position, + * before calling the `arrive` function and continuing execution. + * + * The task will be stopped if the adds a new movement to their walking queue. + * + * @author jameskmonger + */ +export abstract class ActorWalkToTask extends ActorTask { + private _atDestination: boolean = false; + + /** + * `true` if the actor has arrived at the destination. + */ + protected get atDestination(): boolean { + return this._atDestination; + } + + /** + * @param actor The actor executing this task. + * @param destination The destination position. + * @param distance The distance from the destination position that the actor must be within to arrive. + */ + constructor ( + actor: TActor, + protected readonly destination: TTarget, + protected readonly distance = 1, + ) { + super( + actor, + { + interval: 1, + stackType: TaskStackType.NEVER, + stackGroup: TaskStackGroup.ACTION, + breakTypes: [ TaskBreakType.ON_MOVE ], + immediate: false, + repeat: true, + } + ); + + if(destination instanceof Position) { + this.actor.pathfinding.walkTo(destination, { }) + } else { + this.actor.pathfinding.walkTo(new Position(destination.x, destination.y), { }) + } + } + + /** + * Every tick of the task, check if the actor has arrived at the destination. + * + * You can check `this.arrived` to see if the actor has arrived. + * + * If the actor has previously arrived at the destination, but is no longer within distance, + * the task will be stopped. + * + * @returns `true` if the task was stopped this tick, `false` otherwise. + * + * TODO (jameskmonger) unit test this + */ + public execute() { + if (!this.isActive) { + return; + } + + // TODO this uses actual distances rather than tile distances + // is this correct? + const withinDistance = this.actor.position.withinInteractionDistance(this.destination, this.distance) + + // the WalkToTask itself is complete when the actor has arrived at the destination + // execution will now continue in the extended class + if (this._atDestination) { + // TODO consider making this optional + if (!withinDistance) { + this._atDestination = false; + this.stop(); + } + + return; + } + + if (withinDistance) { + this._atDestination = true; + + if (this.onArrive) { + this.onArrive(); + } + } + } +} diff --git a/src/engine/task/impl/actor-world-item-interaction-task.ts b/src/engine/task/impl/actor-world-item-interaction-task.ts new file mode 100644 index 000000000..44ad2c156 --- /dev/null +++ b/src/engine/task/impl/actor-world-item-interaction-task.ts @@ -0,0 +1,79 @@ +import { WorldItem } from '@engine/world'; +import { Actor } from '../../world/actor/actor'; +import { ActorWalkToTask } from './actor-walk-to-task'; + +/** + * A task for an actor to interact with a world item. + * + * This task extends {@link ActorWalkToTask} and will walk the actor to the world item. + * Once the actor is within range of the world item, the task will expose the {@link worldItem} property + * + * @author jameskmonger + */ +export abstract class ActorWorldItemInteractionTask extends ActorWalkToTask { + private _worldItem: WorldItem; + + /** + * Gets the world item that this task is interacting with. + * + * @returns If the world item is still present, and the actor is at the destination, the world item. + * Otherwise, `null`. + * + * TODO (jameskmonger) unit test this + */ + protected get worldItem(): WorldItem | null { + // TODO (jameskmonger) consider if we want to do these checks rather than delegating to the child task + // as currently the subclass has to store it in a subclass property if it wants to use it + // without these checks + if (!this.atDestination) { + return null; + } + + if (!this._worldItem || this._worldItem.removed) { + return null; + } + + return this._worldItem; + } + + /** + * @param actor The actor executing this task. + * @param worldItem The world item to interact with. + */ + constructor ( + actor: TActor, + worldItem: WorldItem, + ) { + super( + actor, + worldItem.position, + 1 + ); + + if (!worldItem) { + this.stop(); + return; + } + + this._worldItem = worldItem; + + } + + /** + * Checks for the continued presence of the world item and stops the task if it is no longer present. + * + * TODO (jameskmonger) unit test this + */ + public execute() { + super.execute(); + + if (!this.isActive || !this.atDestination) { + return; + } + + if (!this._worldItem || this._worldItem.removed) { + this.stop(); + return; + } + } +} diff --git a/src/engine/task/impl/index.ts b/src/engine/task/impl/index.ts new file mode 100644 index 000000000..f3bef0c93 --- /dev/null +++ b/src/engine/task/impl/index.ts @@ -0,0 +1,4 @@ +export { ActorTask } from './actor-task' +export { ActorWalkToTask } from './actor-walk-to-task' +export { ActorWorldItemInteractionTask } from './actor-world-item-interaction-task' +export { ActorLandscapeObjectInteractionTask } from './actor-landscape-object-interaction-task' diff --git a/src/engine/task/index.ts b/src/engine/task/index.ts new file mode 100644 index 000000000..dc98dfe78 --- /dev/null +++ b/src/engine/task/index.ts @@ -0,0 +1,3 @@ +export { Task } from './task' +export { TaskScheduler } from './task-scheduler' +export { TaskStackType, TaskBreakType, TaskStackGroup, TaskConfig } from './types' diff --git a/src/engine/task/task-scheduler.test.ts b/src/engine/task/task-scheduler.test.ts new file mode 100644 index 000000000..5d538ed24 --- /dev/null +++ b/src/engine/task/task-scheduler.test.ts @@ -0,0 +1,106 @@ +import { Task } from './task'; +import { TaskScheduler } from './task-scheduler'; +import { TaskStackType } from './types'; +import { createMockTask } from './utils/_testing'; + +describe('TaskScheduler', () => { + let taskScheduler: TaskScheduler; + beforeEach(() => { + taskScheduler = new TaskScheduler(); + }); + + describe('when enqueueing a task', () => { + let executeMock: jest.Mock; + let task: Task + beforeEach(() => { + ({ task, executeMock } = createMockTask()); + }); + + it('should add the task to the running list when ticked', () => { + taskScheduler.enqueue(task); + taskScheduler.tick(); + expect(executeMock).toHaveBeenCalled(); + }); + + it('should not add the task to the running list until the next tick', () => { + taskScheduler.enqueue(task); + expect(executeMock).not.toHaveBeenCalled(); + }); + + describe('when ticked multiple times', () => { + beforeEach(() => { + taskScheduler.enqueue(task); + taskScheduler.tick(); + taskScheduler.tick(); + }); + + it('should tick the task twice', () => { + expect(executeMock).toHaveBeenCalledTimes(2); + }); + }); + + describe('when the task is stopped', () => { + beforeEach(() => { + taskScheduler.enqueue(task); + taskScheduler.tick(); + }); + + it('should not tick the task after stopping', () => { + task.stop(); + taskScheduler.tick(); + expect(executeMock).toHaveBeenCalledTimes(1); + }); + }); + }); + + describe('when enqueueing a task that cannot stack', () => { + const interval = 0; + const stackType = TaskStackType.NEVER; + const stackGroup = 'foo'; + + let firstExecuteMock: jest.Mock; + let firstTask: Task + beforeEach(() => { + ({ task: firstTask, executeMock: firstExecuteMock } = createMockTask(interval, stackType, stackGroup)); + }); + + it('should stop any other tasks with the same stack group', () => { + const { task: secondTask, executeMock: secondExecuteMock } = createMockTask(interval, stackType, stackGroup); + + taskScheduler.enqueue(firstTask); + taskScheduler.enqueue(secondTask); + taskScheduler.tick(); + + expect(firstExecuteMock).not.toHaveBeenCalled(); + expect(secondExecuteMock).toHaveBeenCalled(); + }); + + it('should not stop any other tasks with a different stack group', () => { + const otherStackGroup = 'bar'; + const { task: secondTask, executeMock: secondExecuteMock } = createMockTask(interval, stackType, otherStackGroup); + + taskScheduler.enqueue(firstTask); + taskScheduler.enqueue(secondTask); + taskScheduler.tick(); + + expect(firstExecuteMock).toHaveBeenCalled(); + expect(secondExecuteMock).toHaveBeenCalled(); + }); + }); + + describe('when clearing the scheduler', () => { + let executeMock: jest.Mock; + let task: Task + beforeEach(() => { + ({ task, executeMock } = createMockTask()); + }); + + it('should stop all tasks', () => { + taskScheduler.enqueue(task); + taskScheduler.tick(); + taskScheduler.clear(); + taskScheduler.tick(); + expect(executeMock).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/src/engine/task/task-scheduler.ts b/src/engine/task/task-scheduler.ts new file mode 100644 index 000000000..090ce5f2d --- /dev/null +++ b/src/engine/task/task-scheduler.ts @@ -0,0 +1,98 @@ +import { Queue } from '@engine/util/queue'; +import { Task } from './task'; +import { TaskStackType } from './types'; + +/** + * A class that ticks tasks in a queue, and removes them when they are no longer active. + * + * @author jameskmonger + */ +export class TaskScheduler { + /** + * A queue of tasks that are waiting to be added to the running list. + */ + private pendingTasks = new Queue(); + + /** + * The list of tasks that are currently running. + */ + private runningTasks: Task[] = []; + + /** + * Register any pending tasks, and tick any running tasks. + */ + public tick(): void { + // Add any pending tasks to the running list + while(this.pendingTasks.isNotEmpty) { + const task = this.pendingTasks.dequeue(); + + if (!task || !task.isActive) { + continue; + } + + this.runningTasks.push(task); + } + + // Use an iterator so that we can remove tasks from the list while iterating + for(const [index, task] of this.runningTasks.entries()) { + if (!task) { + continue; + } + + task.tick(); + + if (!task.isActive) { + this.runningTasks.splice(index, 1); + } + } + } + + /** + * Add a task to the end of the pending queue. + * + * If the task has a stack type of `NEVER`, any other tasks in the scheduler + * with the same stack group will be stopped. + * + * @param task The task to add. + */ + public enqueue(task: Task): void { + if (!task.isActive) { + return; + } + + // if the task can't stack with others of a similar type, we need to stop them + if (task.stackType === TaskStackType.NEVER) { + // Use an iterator so that we can remove tasks from the list while iterating + for(const [index, otherTask] of this.runningTasks.entries()) { + if (!otherTask) { + continue; + } + + if (otherTask.stackGroup === task.stackGroup) { + otherTask.stop(); + this.runningTasks.splice(index, 1); + } + } + + for(const otherTask of this.pendingTasks.items) { + if (!otherTask) { + continue; + } + + if (otherTask.stackGroup === task.stackGroup) { + otherTask.stop(); + } + } + } + + this.pendingTasks.enqueue(task); + } + + /** + * Clear all tasks from the scheduler. + */ + public clear(): void { + this.pendingTasks.clear(); + this.runningTasks = []; + } +} diff --git a/src/engine/task/task.test.ts b/src/engine/task/task.test.ts new file mode 100644 index 000000000..0fbf203c0 --- /dev/null +++ b/src/engine/task/task.test.ts @@ -0,0 +1,213 @@ +import { Task } from './task' +import { TaskStackType } from './types'; +import { createMockTask } from './utils/_testing'; + +describe('Task', () => { + // stacking mechanics are tested in the scheduler + const stackType = TaskStackType.NEVER; + const stackGroup = 'foo'; + const breakType = []; + + describe('when interval is 0', () => { + const interval = 0; + + // no point setting this to true as the interval is 0 + const immediate = false; + + let executeMock: jest.Mock; + let task: Task + + describe('and repeat is true', () => { + const repeat = false; + beforeEach(() => { + ({ task, executeMock } = createMockTask(interval, stackType, stackGroup, immediate, breakType, repeat, )); + }); + + describe('when ticked once', () => { + beforeEach(() => { + task.tick(); + }); + + it('should execute twice', () => { + expect(executeMock).toHaveBeenCalled(); + }); + }); + + describe('when ticked twice', () => { + beforeEach(() => { + task.tick(); + task.tick(); + }); + + it('should execute twice', () => { + expect(executeMock).toHaveBeenCalledTimes(1); + }); + }); + }); + + describe('and repeat is false', () => { + const repeat = false; + beforeEach(() => { + ({ task, executeMock } = createMockTask(interval, stackType, stackGroup, immediate, breakType, repeat)); + }); + + describe('when ticked once', () => { + beforeEach(() => { + task.tick(); + }); + + it('should execute once', () => { + expect(executeMock).toHaveBeenCalledTimes(1); + }); + }); + + describe('when ticked twice', () => { + beforeEach(() => { + task.tick(); + task.tick(); + }); + + it('should execute once', () => { + expect(executeMock).toHaveBeenCalledTimes(1); + }); + }); + }); + }); + + + describe('when interval is 2', () => { + const interval = 2; + + // not testing repeat here as it is tested above + const repeat = false; + + let executeMock: jest.Mock; + let task: Task + + describe('and immediate is true', () => { + const immediate = true; + + beforeEach(() => { + ({ task, executeMock } = createMockTask(interval, stackType, stackGroup, immediate, breakType, repeat)); + }); + + describe('when ticked once', () => { + beforeEach(() => { + task.tick(); + }); + + it('should execute once', () => { + expect(executeMock).toHaveBeenCalledTimes(1); + }); + }); + + describe('when ticked twice', () => { + beforeEach(() => { + task.tick(); + task.tick(); + }); + + // task will execute on ticks 1 and 3 + it('should execute once', () => { + expect(executeMock).toHaveBeenCalledTimes(1); + }); + }); + }); + + describe('and immediate is false', () => { + const immediate = false; + + beforeEach(() => { + ({ task, executeMock } = createMockTask(interval, stackType, stackGroup, immediate, breakType, repeat)); + }); + + describe('when ticked once', () => { + beforeEach(() => { + task.tick(); + }); + + it('should not execute', () => { + expect(executeMock).toHaveBeenCalledTimes(0); + }); + }); + + describe('when ticked twice', () => { + beforeEach(() => { + task.tick(); + task.tick(); + }); + + // task will execute on ticks 2 and 4 + it('should execute once', () => { + expect(executeMock).toHaveBeenCalledTimes(1); + }); + }); + }); + }); + + describe('when there is an onStop callback', () => { + let task: Task; + let onStopMock: jest.Mock; + let executeMock: jest.Mock; + + beforeEach(() => { + onStopMock = jest.fn(); + executeMock = jest.fn(); + task = new class extends Task { + constructor() { + super(); + } + + public execute(): void { + executeMock(); + } + + public onStop(): void { + onStopMock(); + } + } + }); + + describe('when the task is stopped', () => { + beforeEach(() => { + task.stop(); + }); + + it('should call the onStop callback', () => { + expect(onStopMock).toHaveBeenCalled(); + }); + + it('should not call the execute callback', () => { + expect(executeMock).not.toHaveBeenCalled(); + }); + + describe('when the task is ticked', () => { + beforeEach(() => { + task.tick(); + }); + + it('should not call the onStop callback', () => { + expect(onStopMock).toHaveBeenCalledTimes(1); + }); + + it('should not call the execute callback', () => { + expect(executeMock).not.toHaveBeenCalled(); + }); + }); + + describe('when the task is stopped again', () => { + beforeEach(() => { + task.stop(); + }); + + it('should not call the onStop callback', () => { + expect(onStopMock).toHaveBeenCalledTimes(1); + }); + + it('should not call the execute callback', () => { + expect(executeMock).not.toHaveBeenCalled(); + }); + }); + }); + }); +}); diff --git a/src/engine/task/task.ts b/src/engine/task/task.ts new file mode 100644 index 000000000..285115b97 --- /dev/null +++ b/src/engine/task/task.ts @@ -0,0 +1,167 @@ +import { TaskBreakType, TaskConfig, TaskStackGroup, TaskStackType } from './types'; + +const DEFAULT_TASK_CONFIG: Required = { + interval: 1, + stackType: TaskStackType.STACK, + stackGroup: TaskStackGroup.ACTION, + immediate: false, + breakTypes: [], + repeat: true +}; + +function readConfigValue(key: keyof TaskConfig, config?: TaskConfig): any { + if (!config) { + return DEFAULT_TASK_CONFIG[key]; + } + + return config[key] !== undefined ? config[key] : DEFAULT_TASK_CONFIG[key]; +} + +/** + * This Task interface allows us to merge with the Task class + * and add optional methods to the class. + * + * There is no way to add optional methods directly to an abstract class. + * + * @author jameskmonger + */ +export interface Task { + /** + * A callback that is called when the task is stopped. + */ + onStop?(): void; +} + +/** + * A Task which can be ticked and executes after a specified number of ticks. + * + * The task can be configured to execute once, or repeatedly, and can also be executed immediately. + * + * @author jameskmonger + */ +export abstract class Task { + /** + * How the task should be stacked with other tasks of the same stack group. + */ + public readonly stackType: TaskStackType; + + /** + * The stack group for this task. + */ + public readonly stackGroup: string; + + /** + * Conditions under which the task should be broken. + */ + public readonly breakTypes: TaskBreakType[]; + + /** + * The number of ticks between each execution of the task. + */ + private interval: number; + + /** + * The number of ticks remaining before the task is executed. + */ + private ticksRemaining: number; + + /** + * Should the task be repeated indefinitely? + */ + private repeat: boolean; + + private _isActive = true; + + /** + * Is the task active? + */ + public get isActive(): boolean { + return this._isActive; + } + + /** + * @param config the configuration options for the task + * + * @see TaskConfig for more information on the configuration options + */ + public constructor(config?: TaskConfig) { + this.interval = readConfigValue('interval', config); + this.stackType = readConfigValue('stackType', config); + this.stackGroup = readConfigValue('stackGroup', config); + + const immediate = readConfigValue('immediate', config); + this.ticksRemaining = immediate ? 0 : this.interval; + this.breakTypes = readConfigValue('breakTypes', config); + this.repeat = readConfigValue('repeat', config); + } + + /** + * Whether this task breaks on the specified {@link TaskBreakType}. + * + * @param breakType the break type to check + * + * @returns true if the task breaks on the specified break type + */ + public breaksOn(breakType: TaskBreakType): boolean { + return this.breakTypes.includes(breakType); + } + + /** + * Stop the task from executing. + * + * @returns true if the task was stopped, false if the task was already stopped + */ + public stop(): boolean { + // can't stop a task that's already stopped + if (!this._isActive) { + return false; + } + + this._isActive = false; + + if (this.onStop) { + this.onStop(); + } + + return true; + } + + /** + * Tick the task, decrementing the number of ticks remaining. + * + * If the number of ticks remaining reaches zero, the task is executed. + * + * If the task is configured to repeat, the number of ticks remaining is reset to the interval. + * Otherwise, the task is stopped. + */ + public tick(): void { + if (!this._isActive) { + return; + } + + this.ticksRemaining--; + + if (this.ticksRemaining <= 0) { + // TODO maybe track and expose executionCount to this child function + this.execute(); + + // TODO should we allow the repeat count to be specified? + if (this.repeat) { + this.ticksRemaining = this.interval; + } else { + // TODO should I be calling a public function rather than setting the private variable? + this.stop(); + } + } + } + + /** + * The task's execution logic. + * + * Ensure that you call `super.execute()` if you override this method! + * + * TODO (jameskmonger) consider some kind of workaround to enforce a super call + * https://github.com/microsoft/TypeScript/issues/21388#issuecomment-360214959 + */ + public abstract execute(): void; +} diff --git a/src/engine/task/types.ts b/src/engine/task/types.ts new file mode 100644 index 000000000..f7151c598 --- /dev/null +++ b/src/engine/task/types.ts @@ -0,0 +1,81 @@ +/** + * An enum to control the different stacking modes for tasks. + * + * @author jameskmonger + */ +export enum TaskStackType { + /** + * This task cannot be stacked with other tasks of the same stack group. + */ + NEVER, + + /** + * This task can be stacked with other tasks of the same stack group. + */ + STACK, +} + +/** + * An enum to control the different stack groups for tasks. + * + * When a task has a stack type of `NEVER`, other tasks with the same stack group will be cancelled. + * + * @author jameskmonger + */ +export enum TaskStackGroup { + /** + * An action task undertaken by an actor. + */ + ACTION = 'action', +} + +/** + * An enum to control the different breaking modes for tasks. + * + * @author jameskmonger + */ +export enum TaskBreakType { + /** + * This task gets stopped when the player moves + */ + ON_MOVE, +} + +/** + * The configuration options for a Task. + * + * All options are optional as they have default values. + * + * @author jameskmonger + */ +export type TaskConfig = Partial>; diff --git a/src/engine/task/utils/_testing.ts b/src/engine/task/utils/_testing.ts new file mode 100644 index 000000000..ddcdfddd0 --- /dev/null +++ b/src/engine/task/utils/_testing.ts @@ -0,0 +1,31 @@ +import { Task } from '../task'; +import { TaskBreakType, TaskStackGroup, TaskStackType } from '../types'; + +export function createMockTask( + interval: number = 0, + stackType: TaskStackType = TaskStackType.STACK, + stackGroup: string = TaskStackGroup.ACTION, + immediate: boolean = false, + breakTypes: TaskBreakType[] = [], + repeat: boolean = true +){ + const executeMock = jest.fn(); + const task = new class extends Task { + constructor() { + super({ + interval, + stackType, + stackGroup, + immediate, + breakTypes, + repeat + }); + } + + public execute(): void { + executeMock(); + } + } + + return { task, executeMock } +} diff --git a/src/game-engine/util/address.ts b/src/engine/util/address.ts similarity index 100% rename from src/game-engine/util/address.ts rename to src/engine/util/address.ts diff --git a/src/game-engine/util/colors.ts b/src/engine/util/colors.ts similarity index 100% rename from src/game-engine/util/colors.ts rename to src/engine/util/colors.ts diff --git a/src/game-engine/util/data.ts b/src/engine/util/data.ts similarity index 100% rename from src/game-engine/util/data.ts rename to src/engine/util/data.ts diff --git a/src/game-engine/util/error-handling.ts b/src/engine/util/error-handling.ts similarity index 91% rename from src/game-engine/util/error-handling.ts rename to src/engine/util/error-handling.ts index 7c3b495e9..47955c096 100644 --- a/src/game-engine/util/error-handling.ts +++ b/src/engine/util/error-handling.ts @@ -1,4 +1,4 @@ -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; /* * Error handling! Feel free to add other types of errors or warnings here. :) @@ -26,7 +26,7 @@ const warnings = [ ]; export function initErrorHandling(): void { - process.on('unhandledRejection', (error, promise) => { + process.on('unhandledRejection', (error: any, promise) => { for(const t of warnings) { if(error instanceof t) { logger.warn(`Promise cancelled with warning: ${error.name}`); diff --git a/src/game-engine/util/files.ts b/src/engine/util/files.ts similarity index 94% rename from src/game-engine/util/files.ts rename to src/engine/util/files.ts index 504ed0eb6..4618bdb78 100644 --- a/src/game-engine/util/files.ts +++ b/src/engine/util/files.ts @@ -18,7 +18,8 @@ export async function* getFiles(directory: string, list: string[] = [], useWhite const statistics = await stat(path); if(statistics.isDirectory()) { - for await (const child of getFiles(path, list, useWhitelist)) { + // (Jameskmonger) I set the default value of `true` here, not sure if it is correct. + for await (const child of getFiles(path, list, useWhitelist || false)) { yield child; } } else { diff --git a/src/engine/util/index.ts b/src/engine/util/index.ts new file mode 100644 index 000000000..45ee0d306 --- /dev/null +++ b/src/engine/util/index.ts @@ -0,0 +1,10 @@ +export * from './address'; +export * from './colors'; +export * from './data'; +export * from './error-handling'; +export * from './files'; +export * from './num'; +export * from './strings'; +export * from './time'; +export * from './varbits'; +export * from './queue'; diff --git a/src/game-engine/util/num.ts b/src/engine/util/num.ts similarity index 100% rename from src/game-engine/util/num.ts rename to src/engine/util/num.ts diff --git a/src/engine/util/objects.ts b/src/engine/util/objects.ts new file mode 100644 index 000000000..6232c6665 --- /dev/null +++ b/src/engine/util/objects.ts @@ -0,0 +1,52 @@ +/** + * Merge two objects or arrays, first object takes priority in case where the values cannot be merged + * @param objectA + * @param objectB + * @return objectC combination of objectA and objectB + */ +export function deepMerge(objectA: T, objectB: T): T { + if(!objectA) { + return objectB; + } + if(!objectB) { + return objectA; + } + if(Array.isArray(objectA)) { + return [...new Set([...objectA as any, ...objectB as any])] as any; + } + if(typeof objectA === 'object') { + const newObject: T = { ...objectA }; + const keys = [...new Set([...Object.keys(objectA), ...Object.keys(objectB)])]; + keys.forEach((key) => { + if(!objectA[key]) { + newObject[key] = objectB[key]; + return; + } + if(!objectB[key]){ + newObject[key] = objectA[key]; + } + if(Array.isArray(objectA[key])) { + if(!Array.isArray(objectB[key])) { + newObject[key] = [...objectA[key], objectB[key]]; + return; + } + newObject[key] = deepMerge(objectA[key], objectB[key]); + return; + } + if(Array.isArray(objectB[key])) { + if(!Array.isArray(objectA[key])) { + newObject[key] = [...objectB[key], objectA[key]]; + return; + } + console.error('Something is wrong with deepmerger', key, objectA, objectB); + } + if(typeof objectA[key] === 'object' || typeof objectB === 'object') { + newObject[key] = deepMerge(objectA[key], objectB[key]); + return; + } + newObject[key] = objectA[key]; + }) + return newObject; + } + return objectA; +} diff --git a/src/engine/util/queue.test.ts b/src/engine/util/queue.test.ts new file mode 100644 index 000000000..06b3f7b18 --- /dev/null +++ b/src/engine/util/queue.test.ts @@ -0,0 +1,107 @@ +import { Queue } from './queue' + +describe('Queue', () => { + let queue: Queue; + beforeEach(() => { + queue = new Queue(); + }); + + describe('checking Queue length', () => { + it('should be empty when created', () => { + expect(queue.isEmpty).toBe(true); + expect(queue.isNotEmpty).toBe(false); + }); + + it('should be not empty when an item is added', () => { + queue.enqueue(1); + expect(queue.isEmpty).toBe(false); + expect(queue.isNotEmpty).toBe(true); + }); + + it('should be empty when all items are removed', () => { + queue.enqueue(1); + queue.dequeue(); + expect(queue.isEmpty).toBe(true); + expect(queue.isNotEmpty).toBe(false); + }); + + it('should return the correct length', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + expect(queue.length).toBe(3); + }); + }); + + it('should return the correct items', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + expect(queue.items).toEqual([1, 2, 3]); + }); + + describe('when peeking', () => { + it('should return the correct item', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + expect(queue.peek()).toBe(1); + }); + + it('should not remove the item', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + queue.peek(); + expect(queue.items).toEqual([1, 2, 3]); + }); + + it('should return undefined when the queue is empty', () => { + expect(queue.peek()).toBeUndefined(); + }); + }); + + describe('when dequeuing', () => { + it('should return the correct item', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + expect(queue.dequeue()).toBe(1); + }); + + it('should remove the item', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + queue.dequeue(); + expect(queue.items).toEqual([2, 3]); + }); + + it('should return undefined when the queue is empty', () => { + expect(queue.dequeue()).toBeUndefined(); + }); + }); + + describe('when clearing', () => { + it('should remove all items', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + queue.clear(); + expect(queue.items).toEqual([]); + }); + }); + + describe('when iterating', () => { + it('should iterate over all items', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + const items: number[] = []; + for (const item of queue.items) { + items.push(item); + } + expect(items).toEqual([1, 2, 3]); + }); + }); +}) diff --git a/src/engine/util/queue.ts b/src/engine/util/queue.ts new file mode 100644 index 000000000..f20259a4f --- /dev/null +++ b/src/engine/util/queue.ts @@ -0,0 +1,73 @@ +/** + * A first-in-first-out queue. + * + * @author jameskmonger + */ +export class Queue { + private _items: TItem[] = []; + + /** + * Get the items in the queue. + */ + public get items(): TItem[] { + return this._items; + } + + /** + * Get the length of the queue. + */ + public get length(): number { + return this._items.length; + } + + /** + * Is the queue empty? + */ + public get isEmpty(): boolean { + return this._items.length === 0; + } + + /** + * Does the queue contain items? + */ + public get isNotEmpty(): boolean { + return this._items.length > 0; + } + + /** + * Add an item to the end of the queue. + * @param item The item to add. + */ + public enqueue(item: TItem): void { + this._items.push(item); + } + + /** + * Remove an item from the front of the queue. + * @returns The item removed. + */ + public dequeue(): TItem | undefined { + const item = this._items.shift(); + + if (!item) { + return undefined; + } + + return item; + } + + /** + * Get the item at the front of the queue without removing it. + * @returns The item at the front of the queue. + */ + public peek(): TItem { + return this._items[0]; + } + + /** + * Remove all items from the queue. + */ + public clear(): void { + this._items = []; + } +} diff --git a/src/game-engine/util/strings.ts b/src/engine/util/strings.ts similarity index 96% rename from src/game-engine/util/strings.ts rename to src/engine/util/strings.ts index 0df6ee25c..a2f5a21a0 100644 --- a/src/game-engine/util/strings.ts +++ b/src/engine/util/strings.ts @@ -1,6 +1,6 @@ import { hexToHexString } from '@engine/util/colors'; import { FontName } from '@runejs/filestore'; -import { filestore } from '@engine/game-server'; +import { filestore } from '@server/game/game-server'; export const startsWithVowel = (str: string): boolean => { str = str.trim().toLowerCase(); @@ -11,7 +11,7 @@ export const startsWithVowel = (str: string): boolean => { }; -function getFont(font: number | string) { +function getFont(font?: number | string) { if (font && typeof font === 'number') { return filestore.fontStore.getFontById(font); } else if (font && typeof font === 'string') { @@ -58,7 +58,7 @@ const charWidths = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // TODO refactor a bit export function wrapText(text: string, maxWidth: number, font?: number | string): string[] { - const lines = []; + const lines: string[] = []; const selectedFont = getFont(font); const colorQueue: string[] = []; const decorationQueue: string[] = []; @@ -120,7 +120,7 @@ export function wrapText(text: string, maxWidth: number, font?: number | string) if (rendered) { currentLine += char; } - if (!hidden && currentTagIndex == -1) { + if (!hidden && currentTagIndex == -1 && char !== undefined) { const charWidth = selectedFont.getCharWidth(char); currentWidth += charWidth; } @@ -171,7 +171,7 @@ const VALID_CHARS = ['_', 'a', 'b', 'c', 'd', '*', '(', ')', '-', '+', '=', ':', ';', '.', '>', '<', ',', '"', '[', ']', '|', '?', '/', '`']; -export function longToString(nameLong: BigInt): string { +export function longToString(nameLong: bigint): string { let ac: string = ''; while(nameLong !== BigInt(0)) { const l1 = nameLong; diff --git a/src/game-engine/util/time.ts b/src/engine/util/time.ts similarity index 100% rename from src/game-engine/util/time.ts rename to src/engine/util/time.ts diff --git a/src/game-engine/util/varbits.ts b/src/engine/util/varbits.ts similarity index 77% rename from src/game-engine/util/varbits.ts rename to src/engine/util/varbits.ts index 9b955d351..3f8b616df 100644 --- a/src/game-engine/util/varbits.ts +++ b/src/engine/util/varbits.ts @@ -1,10 +1,6 @@ -import { filestore } from '@engine/game-server'; -import { findNpc } from '@engine/config'; -import { logger } from '@runejs/core'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { Player } from '@engine/world/actor/player/player'; +import { filestore } from '@server/game/game-server'; -const varbitMasks = []; +const varbitMasks: number[] = []; /** * Returns the index to morph actor/object into, based on set config @@ -21,6 +17,11 @@ export function getVarbitMorphIndex(varbitId, playerConfig) { } } const varbitDefinition = filestore.configStore.varbitStore.getVarbit(varbitId); + + if(!varbitDefinition) { + throw new Error(`Could not find varbit definition for id ${varbitId}`); + } + const mostSignificantBit = varbitDefinition.mostSignificantBit; const configId = varbitDefinition.index; const leastSignificantBit = varbitDefinition.leastSignificantBit; @@ -29,4 +30,3 @@ export function getVarbitMorphIndex(varbitId, playerConfig) { const configValue = playerConfig && playerConfig[configId] ? playerConfig[configId] : 0; return ((configValue) >> leastSignificantBit & i_8_); } - diff --git a/src/game-engine/world/actor/actor.ts b/src/engine/world/actor/actor.ts similarity index 52% rename from src/game-engine/world/actor/actor.ts rename to src/engine/world/actor/actor.ts index 617953686..005d755d2 100644 --- a/src/game-engine/world/actor/actor.ts +++ b/src/engine/world/actor/actor.ts @@ -1,41 +1,47 @@ -import { WalkingQueue } from './walking-queue'; -import { ItemContainer } from '../items/item-container'; -import { Animation, DamageType, Graphic, UpdateFlags } from './update-flags'; -import { Npc } from './npc/npc'; -import { Skill, Skills } from '@engine/world/actor/skills'; -import { Item } from '@engine/world/items/item'; -import { Position } from '@engine/world/position'; -import { DirectionData, directionFromIndex } from '@engine/world/direction'; -import { Pathfinding } from '@engine/world/actor/pathfinding'; import { Subject } from 'rxjs'; import { filter, take } from 'rxjs/operators'; -import { world } from '@engine/game-server'; -import { WorldInstance } from '@engine/world/instances'; -import { Player } from '@engine/world/actor/player/player'; -import { ActionCancelType, ActionPipeline } from '@engine/world/action'; + import { LandscapeObject } from '@runejs/filestore'; -import { Behavior } from './behaviors/behavior'; -import { soundIds } from '../config/sound-ids'; -import { animationIds } from '../config/animation-ids'; -import { findNpc } from '../../config'; -import { itemIds } from '../config/item-ids'; -import { Attack, AttackDamageType } from './player/attack'; -import { Effect, EffectType } from './effect'; + +import { DefensiveBonuses, OffensiveBonuses, SkillBonuses } from '@engine/config'; +import { Position, DirectionData, directionFromIndex, WorldInstance, activeWorld } from '@engine/world'; +import { Item, ItemContainer } from '@engine/world/items'; +import { ActionCancelType, ActionPipeline } from '@engine/action'; + +import { WalkingQueue } from './walking-queue'; +import { Animation, Graphic, UpdateFlags } from './update-flags'; +import { Skills } from './skills'; +import { Pathfinding } from './pathfinding'; +import { ActorMetadata } from './metadata'; +import { Task, TaskScheduler } from '@engine/task'; +import { logger } from '@runejs/common'; + + +export type ActorType = 'player' | 'npc'; + /** - * Handles an actor within the game world. + * Handles an entity within the game world. */ export abstract class Actor { - - + public readonly type: ActorType; public readonly updateFlags: UpdateFlags = new UpdateFlags(); public readonly skills: Skills = new Skills(this); public readonly walkingQueue: WalkingQueue = new WalkingQueue(this); public readonly inventory: ItemContainer = new ItemContainer(28); public readonly bank: ItemContainer = new ItemContainer(376); public readonly actionPipeline = new ActionPipeline(this); - public readonly metadata: { [key: string]: any } = {}; + + /** + * The map of available metadata for this actor. + * + * You cannot guarantee that this will be populated with data, so you should always check for the existence of the + * metadata you are looking for before using it. + * + * @author jameskmonger + */ + public readonly metadata: Partial = {}; /** * @deprecated - use new action system instead @@ -44,197 +50,100 @@ export abstract class Actor { public pathfinding: Pathfinding = new Pathfinding(this); public lastMovementPosition: Position; - // #region Behaviors and Combat flags/checks - public inCombat: boolean = false; - public meleeDistance: number = 1; - public Behaviors: Behavior[] = []; - public isDead: boolean = false; - public combatTargets: Actor[] = []; - public hitPoints = this.skills.hitpoints.level * 4; - public maxHitPoints = this.skills.hitpoints.level * 4; - - public get damageType() { - return this._damageType; - } - public set damageType(value) { - this._damageType = value; - } - public effects: Effect[] = []; //spells, effects, prayers, etc - + protected randomMovementInterval; + protected _instance: WorldInstance | null = null; + + /** + * Is this actor currently active? If true, the actor will have its task queue processed. + * + * This is true for players that are currently logged in, and NPCs that are currently in the world. + */ + protected active: boolean; + /** * @deprecated - use new action system instead */ - private _busy: boolean; + private _busy: boolean = false; private _position: Position; private _lastMapRegionUpdatePosition: Position; private _worldIndex: number; private _walkDirection: number; private _runDirection: number; private _faceDirection: number; - private _instance: WorldInstance = null; - private _damageType = AttackDamageType.Crush; + private _bonuses: { offensive: OffensiveBonuses, defensive: DefensiveBonuses, skill: SkillBonuses }; + + private readonly scheduler = new TaskScheduler(); - protected constructor() { + protected constructor(actorType: ActorType) { + this.type = actorType; this._walkDirection = -1; this._runDirection = -1; this._faceDirection = 6; - this._busy = false; - } - - public get highestCombatSkill(): Skill { - const attack = this.skills.getLevel('attack'); - const magic = this.skills.getLevel('magic'); - const ranged = this.skills.getLevel('ranged'); - - if (ranged > magic && ranged > ranged) return ranged; - else if (magic > attack && magic > ranged) return magic; - else return attack; - } - - //https://oldschool.runescape.wiki/w/Attack_range#:~:text=All%20combat%20magic%20spells%20have,also%20allow%20longrange%20attack%20style - // range should be within 10 tiles for magic - // range should be within 7 for magic staff - // https://www.theoatrix.net/post/how-defence-works-in-osrs - // https://oldschool.runescape.wiki/w/Damage_per_second/Magic - // https://oldschool.runescape.wiki/w/Successful_hit - // https://oldschool.runescape.wiki/w/Combat_level#:~:text=Calculating%20combat%20level,-Simply&text=Add%20your%20Strength%20and%20Attack,have%20your%20melee%20combat%20level.&text=Multiply%20this%20by%200.325%20and,have%20your%20magic%20combat%20level - // https://oldschool.runescape.wiki/w/Damage_per_second/Melee#:~:text=1%20Step%20one%3A%20Calculate%20the%20effective%20strength%20level%3B,1.7%20Step%20seven%3A%20Calculate%20the%20melee%20damage%20output - public getAttackRoll(defender): Attack { - - //the amount of damage is random from 0 to Max - //stance modifiers - const _stance_defense = 3; - const _stance_accurate = 0; - const _stance_controlled = 1; - - // base level - // ToDo: calculate prayer effects - // round decimal result calulcation up - // add 8 - // ToDo: add void bonues (effects) - // round result down - let equipmentBonus = 0; - if (this.isPlayer) { - const player = (this as unknown as Player); - equipmentBonus = player.bonuses.offensive.crush; - } - if (equipmentBonus == 0) equipmentBonus = 1; - /* - * To calculate your maximum hit: - - Effective strength level - Multiply by(Equipment Melee Strength + 64) - Add 320 - Divide by 640 - Round down to nearest integer - Multiply by gear bonus - Round down to nearest integer - */ - const stanceModifier = _stance_accurate; - const strengthLevel = (this.skills.attack.level + stanceModifier + 8); - let attackCalc = strengthLevel * (equipmentBonus + 64) + 320; - attackCalc = Math.round(attackCalc / 640); - //console.log(`strengthLevel = ${strengthLevel} \r\n attackCalc = ${attackCalc} \r\n equipmentBonus = ${equipmentBonus}`); - const maximumHit = Math.round(attackCalc * equipmentBonus); - - /* - To calculate your effective attack level: - - (Attack level + Attack level boost) * prayer bonus - Round down to nearest integer - + 3 if using the accurate attack style, +1 if using controlled - + 8 - Multiply by 1.1 if wearing void - Round down to nearest integer - */ - const attackLevel = this.skills.attack.level; - let effectiveAttackLevel = attackLevel; - - //Prayer/Effect bonus - calculate ALL the good and bad effects at once! (prayers, and magic effects, etc.) - this.effects.filter(a => a.EffectType === EffectType.Attack).forEach((effect) => { - effectiveAttackLevel += (attackLevel * effect.Modifier); - }); - effectiveAttackLevel = Math.round(effectiveAttackLevel) + stanceModifier; - - /* - * Calculate the Attack roll - Effective attack level * (Equipment Attack bonus + 64) - Multiply by gear bonus - Round down to nearest integer - * */ - let attack = new Attack(); - attack.damageType = this.damageType ?? AttackDamageType.Crush; - attack.attackRoll = Math.round(effectiveAttackLevel * (equipmentBonus + 64)); - attack = defender.getDefenseRoll(attack); - attack.maximumHit = maximumHit; - if (attack.attackRoll >= attack.defenseRoll) attack.hitChance = 1 - ((attack.defenseRoll + 2) / (2 * (attack.attackRoll + 1))) - if (attack.attackRoll < attack.defenseRoll) attack.hitChance = attack.attackRoll / (2 * attack.defenseRoll + 1); - - attack.damage = Math.round((maximumHit * attack.hitChance) / 2); - return attack; - } - public getDefenseRoll(attack: Attack): Attack { - //attack need to know the damage roll, which is the item bonuses the weapon damage type etc. - - - //stance modifiers - const _stance_defense = 3; - const _stance_accurate = 0; - const _stance_controlled = 1; - - // base level - // calculate prayer effects - // round decimal result calulcation up - // add 8 - // ToDo: add void bonues (effects) - // round result down - - const equipmentBonus: number = this.isPlayer ? (this as unknown as Player).bonuses.defensive.crush : 0; //object prototyping to find property by name (JS style =/) - - const stanceModifier: number = _stance_accurate; - - - attack.defenseRoll = (this.skills.defence.level + stanceModifier + 8) * (equipmentBonus + 64); - //Prayer/Effect bonus - calculate ALL the good and bad effects at once! (prayers, and magic effects, etc.) - this.effects.filter(a => a.EffectType === EffectType.BoostDefense || a.EffectType === EffectType.LowerDefense).forEach((effect) => { - attack.defenseRoll += (this.skills.defence.level * effect.Modifier); - }); - attack.defenseRoll = Math.round(attack.defenseRoll); - return attack; - //+ stance modifier - } - // #endregion - - public damage(amount: number, damageType: DamageType = DamageType.DAMAGE) { - const armorReduction = 0; - const spellDamageReduction = 0; - const poisonReistance = 0; - amount -= armorReduction; - this.hitPoints -= amount; - this.skills.setHitpoints(this.hitPoints); - this.updateFlags.addDamage(amount, amount === 0 ? DamageType.NO_DAMAGE : damageType, - this.hitPoints, this.maxHitPoints); - //this actor should respond when hit - world.playLocationSound(this.position, soundIds.npc.human.noArmorHitPlayer,5) - this.playAnimation(this.getBlockAnimation()); + this.clearBonuses(); } + /** + * Instantiate a task with the Actor instance and a set of arguments. + * + * @param taskClass The task class to instantiate. Must be a subclass of {@link Task} + * @param args The arguments to pass to the task constructor + * + * If the task has a stack type of `NEVER`, other tasks in the same {@link TaskStackGroup} will be cancelled. + */ + public enqueueTask(taskClass: new (actor: Actor) => Task, ...args: never[]): void; + public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => Task, args: [ T1, T2, T3, T4, T5, T6 ]): void; + public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => Task, args: [ T1, T2, T3, T4, T5 ]): void; + public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Task, args: [ T1, T2, T3, T4 ]): void; + public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2, arg3: T3) => Task, args: [ T1, T2, T3 ]): void; + public enqueueTask(taskClass: new (actor: Actor, arg1: T1, arg2: T2) => Task, args: [ T1, T2 ]): void; + public enqueueTask(taskClass: new (actor: Actor, arg1: T1) => Task, args: [ T1 ]): void; + public enqueueTask(taskClass: new (actor: Actor, ...args: T[]) => Task, args: T[]): void { + if (!this.active) { + logger.warn(`Attempted to instantiate task for inactive actor`); + return; + } + if (args) { + this.enqueueBaseTask( + new taskClass(this, ...args) + ); + } else { + this.enqueueBaseTask( + new taskClass(this) + ); + } + } - //public damage(amount: number, damageType: DamageType = DamageType.DAMAGE): 'alive' | 'dead' { - // let remainingHitpoints: number = this.skills.hitpoints.level - amount; - // const maximumHitpoints: number = this.skills.hitpoints.levelForExp; - // if(remainingHitpoints < 0) { - // remainingHitpoints = 0; - // } + /** + * Adds a task to the actor's scheduler queue. These tasks will be stopped when they become inactive. + * + * If the task has a stack type of `NEVER`, other tasks in the same group will be cancelled. + * + * @param task The task to add + */ + public enqueueBaseTask(task: Task): void { + if (!this.active) { + logger.warn(`Attempted to enqueue task for inactive actor`); + return; + } - // this.skills.setHitpoints(remainingHitpoints); - // this.updateFlags.addDamage(amount, amount === 0 ? DamageType.NO_DAMAGE : damageType, - // remainingHitpoints, maximumHitpoints); + this.scheduler.enqueue(task); + } - // return remainingHitpoints === 0 ? 'dead' : 'alive'; - //} + public clearBonuses(): void { + this._bonuses = { + offensive: { + speed: 0, stab: 0, slash: 0, crush: 0, magic: 0, ranged: 0 + }, + defensive: { + stab: 0, slash: 0, crush: 0, magic: 0, ranged: 0 + }, + skill: { + strength: 0, prayer: 0 + } + }; + } /** * Waits for the actor to reach the specified position before resolving it's promise. @@ -287,7 +196,7 @@ export abstract class Actor { } clearInterval(inter); - this.metadata.walkingTo = null; + this.metadata.walkingTo = undefined; } }, 100); }); @@ -340,12 +249,13 @@ export abstract class Actor { public follow(target: Actor): void { this.face(target, false, false, false); - this.metadata['following'] = target; + this.metadata.following = target; this.moveBehind(target); const subscription = target.walkingQueue.movementEvent.subscribe(() => { if(!this.moveBehind(target)) { - this.actionsCancelled.next(null); + // (Jameskmonger) actionsCancelled is deprecated, casting this to satisfy the typecheck for now + this.actionsCancelled.next(null as unknown as ActionCancelType); } }); @@ -355,7 +265,7 @@ export abstract class Actor { ).subscribe(() => { subscription.unsubscribe(); this.face(null); - delete this.metadata['following']; + delete this.metadata.following; }); } @@ -369,7 +279,7 @@ export abstract class Actor { if(distance <= 1) { return false; } - + if(distance > 16) { this.clearFaceActor(); this.metadata.faceActorClearedByWalking = true; @@ -384,28 +294,6 @@ export abstract class Actor { return true; } - public tail(target: Actor): void { - this.face(target, false, false, false); - - if(this.metadata.tailing && this.metadata.tailing.equals(target)) { - return; - } - - this.metadata['tailing'] = target; - - this.moveTo(target); - const subscription = target.walkingQueue.movementEvent.subscribe(async () => this.moveTo(target)); - - this.actionsCancelled.pipe( - filter(type => type !== 'pathing-movement'), - take(1) - ).subscribe(() => { - subscription.unsubscribe(); - this.face(null); - delete this.metadata['tailing']; - }); - } - public face(face: Position | Actor | null, clearWalkingQueue: boolean = true, autoClear: boolean = true, clearedByWalking: boolean = true): void { if(face === null) { this.clearFaceActor(); @@ -417,8 +305,8 @@ export abstract class Actor { this.updateFlags.facePosition = face; } else if(face instanceof Actor) { this.updateFlags.faceActor = face; - this.metadata['faceActor'] = face; - this.metadata['faceActorClearedByWalking'] = clearedByWalking; + this.metadata.faceActor = face; + this.metadata.faceActorClearedByWalking = clearedByWalking; if(autoClear) { setTimeout(() => { @@ -434,13 +322,13 @@ export abstract class Actor { } public clearFaceActor(): void { - if(this.metadata['faceActor']) { + if(this.metadata.faceActor) { this.updateFlags.faceActor = null; - this.metadata['faceActor'] = undefined; + this.metadata.faceActor = undefined; } } - public playAnimation(animation: number | Animation): void { + public playAnimation(animation: number | Animation | null): void { if(typeof animation === 'number') { animation = { id: animation, delay: 0 }; } @@ -503,10 +391,10 @@ export abstract class Actor { return; } - if(this instanceof Npc) { - const nearbyPlayers = world.findNearbyPlayers(this.position, 24, this.instanceId); + if(this.isNpc) { + const nearbyPlayers = activeWorld.findNearbyPlayers(this.position, 24, this.instance?.instanceId); if(nearbyPlayers.length === 0) { - // No need for this NPC to move if there are no players nearby to see it + // No need for this actor to move if there are no players nearby to witness it, save some memory. :) return; } } @@ -517,8 +405,8 @@ export abstract class Actor { return; } - let px: number; - let py: number; + let px = this.position.x; + let py = this.position.y; let movementAllowed = false; while(!movementAllowed) { @@ -553,11 +441,8 @@ export abstract class Actor { let valid = true; - if(this instanceof Npc) { - if(px > this.initialPosition.x + this.movementRadius || px < this.initialPosition.x - this.movementRadius - || py > this.initialPosition.y + this.movementRadius || py < this.initialPosition.y - this.movementRadius) { - valid = false; - } + if(!this.withinBounds(px, py)) { + valid = false; } movementAllowed = valid; @@ -575,15 +460,15 @@ export abstract class Actor { return; } - let px: number; - let py: number; + let px = this.position.x; + let py = this.position.y; let movementAllowed = false; while(!movementAllowed) { px = this.position.x; py = this.position.y; - const movementDirection: DirectionData = directionFromIndex(direction); + const movementDirection = directionFromIndex(direction); if(!movementDirection) { return; } @@ -592,18 +477,13 @@ export abstract class Actor { px += movementDirection.deltaX; py += movementDirection.deltaY; - if(this instanceof Npc) { - if(px > this.initialPosition.x + this.movementRadius || px < this.initialPosition.x - this.movementRadius - || py > this.initialPosition.y + this.movementRadius || py < this.initialPosition.y - this.movementRadius) { - valid = false; - } + if(!this.withinBounds(px, py)) { + valid = false; } } movementAllowed = valid; - - } if(px !== this.position.x || py !== this.position.y) { @@ -613,8 +493,32 @@ export abstract class Actor { } } - public abstract getAttackAnimation(): number; - public abstract getBlockAnimation(): number; + public withinBounds(x: number, y: number): boolean { + return true; + } + + /** + * Initialise the actor. + */ + protected init() { + this.active = true; + } + + /** + * Destroy this actor. + * + * This will stop the processing of its action queue. + */ + protected destroy() { + this.active = false; + + this.scheduler.clear(); + } + + protected tick() { + this.scheduler.tick(); + } + public abstract equals(actor: Actor): boolean; public get position(): Position { @@ -678,38 +582,22 @@ export abstract class Actor { } public get instance(): WorldInstance { - return this._instance || world.globalInstance; + return this._instance || activeWorld.globalInstance; } - public set instance(value: WorldInstance) { - if(this instanceof Player) { - const currentInstance = this._instance; - if(currentInstance?.instanceId) { - currentInstance.removePlayer(this); - } - - if(value) { - value.addPlayer(this); - } - } - + public set instance(value: WorldInstance | null) { this._instance = value; } public get isPlayer(): boolean { - return this instanceof Player; + return this.type === 'player'; } public get isNpc(): boolean { - return this instanceof Npc; + return this.type === 'npc'; } - public get type(): { player?: Player, npc?: Npc } { - return { - player: this.isPlayer ? this as unknown as Player : undefined, - npc: this.isNpc ? this as unknown as Npc : undefined - }; + public get bonuses(): { offensive: OffensiveBonuses, defensive: DefensiveBonuses, skill: SkillBonuses } { + return this._bonuses; } - - } diff --git a/src/game-engine/world/actor/combat.ts b/src/engine/world/actor/combat.ts similarity index 100% rename from src/game-engine/world/actor/combat.ts rename to src/engine/world/actor/combat.ts diff --git a/src/game-engine/world/actor/dialogue.ts b/src/engine/world/actor/dialogue.ts similarity index 79% rename from src/game-engine/world/actor/dialogue.ts rename to src/engine/world/actor/dialogue.ts index 6e13b4e42..9754bd93a 100644 --- a/src/game-engine/world/actor/dialogue.ts +++ b/src/engine/world/actor/dialogue.ts @@ -1,10 +1,10 @@ -import { Npc } from '@engine/world/actor/npc/npc'; +import { Npc } from '@engine/world/actor/npc'; import { Player } from '@engine/world/actor/player/player'; -import { filestore } from '@engine/game-server'; -import { logger } from '@runejs/core'; +import { filestore } from '@server/game/game-server'; +import { logger } from '@runejs/common'; import _ from 'lodash'; import { wrapText } from '@engine/util/strings'; -import { findNpc } from '@engine/config'; +import { findNpc } from '@engine/config/config-handler'; import { ParentWidget, TextWidget } from '@runejs/filestore'; @@ -131,27 +131,27 @@ function wrapDialogueText(text: string, type: 'ACTOR' | 'TEXT'): string[] { width = widget.width; break; default: - throw new Error(`Unhandled widget type: ${type}`); + throw new Error(`Unhandled widget type: ${ type }`); } return wrapText(text, width, widget.fontId); } -function parseDialogueFunctionArgs(func: Function): string[] { +function parseDialogueFunctionArgs(func: Function): string[] | null { const str = func.toString(); - if(!str) { + if (!str) { return null; } const argEndIndex = str.indexOf('=>'); - if(argEndIndex === -1) { + if (argEndIndex === -1) { return null; } const arg = str.substring(0, argEndIndex).replace(/[\\(\\) ]/g, '').trim(); - if(!arg || arg.length === 0) { + if (!arg || arg.length === 0) { return null; } @@ -172,7 +172,8 @@ interface NpcParticipant { } class DialogueFunction { - constructor(public type: string, public execute: Function) {} + constructor(public type: string, public execute: Function) { + } } export const execute = (execute: Function): DialogueFunction => new DialogueFunction('execute', execute); @@ -228,7 +229,7 @@ interface SubDialogueTreeAction extends DialogueAction { function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], dialogueTree: DialogueTree): ParsedDialogueTree { const parsedDialogueTree: ParsedDialogueTree = []; - let carryoverDialogue = []; + let carryoverDialogue: string[] = []; for (let i = 0; i < dialogueTree.length; i++) { const dialogueAction = dialogueTree[i]; @@ -245,14 +246,18 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di let args = parseDialogueFunctionArgs(dialogueAction); if (args === null) { - args = ['()']; + args = [ '()' ]; } const dialogueType = args[0]; - let tag: string = null; + let tag: string | null = null; if (args.length === 2 && typeof args[1] === 'string') { - player.metadata.dialogueIndices[args[1]] = i; + if (player.metadata.dialogueIndices) { + player.metadata.dialogueIndices[args[1]] = i; + } else { + logger.warn('Player metadata does not contain dialogueIndices'); + } tag = args[1]; } @@ -293,9 +298,14 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di const trees = (result as any[]).filter((option, index) => index % 2 !== 0); const optionsDialogueAction: OptionsDialogueAction = { options: {}, - tag, type: 'OPTIONS' + tag: tag || '', + type: 'OPTIONS' }; + if (!tag) { + logger.warn('No tag provided for options dialogue.'); + } + for (let j = 0; j < options.length; j++) { const option = options[j]; const tree = parseDialogueTree(player, npcParticipants, trees[j]); @@ -319,7 +329,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di } else if (dialogueType === 'titled') { // Text-only dialogue (no option to continue). - const [title, text] = dialogueAction(); + const [ title, text ] = dialogueAction(); const lines = wrapDialogueText(text, 'TEXT'); while (lines.length < 4) { @@ -335,8 +345,8 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di } else { // Player or Npc dialogue. - let dialogueDetails: [Emote, string]; - let npc: Npc | number | string; + let dialogueDetails: [ Emote, string ]; + let npc: Npc | number | string = -1; if (dialogueType !== 'player') { const participant = npcParticipants.find(p => p.key === dialogueType) as NpcParticipant; @@ -359,6 +369,10 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di dialogueDetails = dialogueAction(player); } + // TODO (Jameskmonger) not sure if this check is needed, added it when getting TypeScript types into strict mode + if (npc === -1) { + throw new Error('No npc found for dialogue action.'); + } const emote = dialogueDetails[0] as Emote; const text = carryoverDialogue.join(' ') + dialogueDetails[1] as string; @@ -367,7 +381,11 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di let lines = wrapDialogueText(text, 'ACTOR'); // logger.info('length = ' + lines.length + ' - lines equals this: ' + lines); - const animation = nonLineEmotes.indexOf(emote) !== -1 ? EmoteAnimation[emote] : EmoteAnimation[`${emote}_${lines.length}LINE`]; + const animation = nonLineEmotes.indexOf(emote) !== -1 ? EmoteAnimation[emote] : EmoteAnimation[`${ emote }_${ lines.length }LINE`]; + + if (!tag) { + logger.warn('No tag provided for npc dialogue.'); + } if (dialogueType !== 'player') { if (lines.length > 4) { @@ -376,17 +394,26 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di lines = lines.slice(0, 4); const npcDialogueAction: NpcDialogueAction = { - npcId: npc as number, animation, lines, tag, type: 'NPC' + npcId: npc as number, + animation, + lines, + tag: tag || '', + type: 'NPC' }; + parsedDialogueTree.push(npcDialogueAction); lines = copyOfLines.slice(0, copyOfLines.length); carryoverDialogue = lines.slice(4, lines.length) as string[]; lines = carryoverDialogue; - if(i === dialogueTree.length - 1 && lines.length <= 4) { + if (i === dialogueTree.length - 1 && lines.length <= 4) { const npcDialogueAction: NpcDialogueAction = { - npcId: npc as number, animation, lines, tag, type: 'NPC' + npcId: npc as number, + animation, + lines, + tag: tag || '', + type: 'NPC' }; parsedDialogueTree.push(npcDialogueAction); @@ -394,14 +421,22 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di } } else { const npcDialogueAction: NpcDialogueAction = { - npcId: npc as number, animation, lines, tag, type: 'NPC' + npcId: npc as number, + animation, + lines, + tag: tag || '', + type: 'NPC' }; parsedDialogueTree.push(npcDialogueAction); } } else { const playerDialogueAction: PlayerDialogueAction = { - player, animation, lines, tag, type: 'PLAYER' + player, + animation, + lines, + tag: tag || '', + type: 'PLAYER' }; parsedDialogueTree.push(playerDialogueAction); @@ -414,7 +449,7 @@ function parseDialogueTree(player: Player, npcParticipants: NpcParticipant[], di async function runDialogueAction(player: Player, dialogueAction: string | DialogueFunction | DialogueAction, tag?: string | undefined | false, additionalOptions?: AdditionalOptions): Promise { - if(dialogueAction instanceof DialogueFunction && !tag) { + if (dialogueAction instanceof DialogueFunction && !tag) { // Code execution dialogue. dialogueAction.execute(); return tag; @@ -422,10 +457,10 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog dialogueAction = dialogueAction as DialogueAction; - if(dialogueAction.type === 'GOTO' && !tag) { + if (dialogueAction.type === 'GOTO' && !tag) { // Goto dialogue. const goToAction = (dialogueAction as GoToAction); - if(typeof goToAction.to === 'function') { + if (typeof goToAction.to === 'function') { const goto: string = goToAction.to(); await runParsedDialogue(player, player.metadata.dialogueTree, goto, additionalOptions); } else { @@ -434,94 +469,102 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog return tag; } - let widgetId: number; + let widgetId: number = -1; let isOptions = false; - if(dialogueAction.type === 'OPTIONS') { + if (dialogueAction.type === 'OPTIONS') { // Option dialogue. const optionsAction = dialogueAction as OptionsDialogueAction; isOptions = true; const options = Object.keys(optionsAction.options); const trees = options.map(option => optionsAction.options[option]); - if(tag === undefined || dialogueAction.tag === tag) { + if (tag === undefined || dialogueAction.tag === tag) { tag = undefined; widgetId = optionWidgetIds[options.length - 2]; - for(let i = 0; i < options.length; i++) { + for (let i = 0; i < options.length; i++) { player.outgoingPackets.updateWidgetString(widgetId, 1 + i, options[i]); } - } else if(tag !== undefined) { - for(let i = 0; i < options.length; i++) { + } else if (tag !== undefined) { + for (let i = 0; i < options.length; i++) { const tree = trees[i]; const didRun = await runParsedDialogue(player, tree, tag, additionalOptions); - if(didRun) { + if (didRun) { return; } } } - } else if(dialogueAction.type === 'TEXT') { + } else if (dialogueAction.type === 'TEXT') { // Text-only dialogue. - if(tag === undefined || dialogueAction.tag === tag) { + if (tag === undefined || dialogueAction.tag === tag) { tag = undefined; const textDialogueAction = dialogueAction as TextDialogueAction; const lines = textDialogueAction.lines; - if(lines.length > 5) { - throw new Error(`Too many lines for text dialogue! Dialogue has ${lines.length} lines but ` + - `the maximum is 5: ${JSON.stringify(lines)}`); + if (lines.length > 5) { + throw new Error(`Too many lines for text dialogue! Dialogue has ${ lines.length } lines but ` + + `the maximum is 5: ${ JSON.stringify(lines) }`); } widgetId = (textDialogueAction.canContinue ? continuableTextWidgetIds : textWidgetIds)[lines.length - 1]; - for(let i = 0; i < lines.length; i++) { + for (let i = 0; i < lines.length; i++) { player.outgoingPackets.updateWidgetString(widgetId, i, lines[i]); } } - } else if(dialogueAction.type === 'TITLED') { + } else if (dialogueAction.type === 'TITLED') { // Text-only dialogue. - if(tag === undefined || dialogueAction.tag === tag) { + if (tag === undefined || dialogueAction.tag === tag) { tag = undefined; const titledDialogueAction = dialogueAction as TitledTextDialogueAction; const { title, lines } = titledDialogueAction; - if(lines.length > 4) { - throw new Error(`Too many lines for titled dialogue! Dialogue has ${lines.length} lines but ` + - `the maximum is 4: ${JSON.stringify(lines)}`); + if (lines.length > 4) { + throw new Error(`Too many lines for titled dialogue! Dialogue has ${ lines.length } lines but ` + + `the maximum is 4: ${ JSON.stringify(lines) }`); } widgetId = titledTextWidgetId; player.outgoingPackets.updateWidgetString(widgetId, 0, title); - for(let i = 0; i < lines.length; i++) { + for (let i = 0; i < lines.length; i++) { player.outgoingPackets.updateWidgetString(widgetId, i + 1, lines[i]); } } - } else if(dialogueAction.type === 'SUBTREE') { + } else if (dialogueAction.type === 'SUBTREE') { // Dialogue sub-tree. const action = (dialogueAction as SubDialogueTreeAction); - if(dialogueAction.tag === tag) { + if (!action.npcParticipants) { + // (Jameskmonger) I added this log because the TypeScript types allow for this to be undefined, but + // parseDialogueTree requires it. I'm not sure if it can be undefined in practice. + logger.warn('No NPC participants for dialogue action'); + } + // (Jameskmonger) default value added here + const npcParticipants = action.npcParticipants || []; + + if (dialogueAction.tag === tag) { const originalIndices = _.cloneDeep(player.metadata.dialogueIndices || {}); const originalTree = _.cloneDeep(player.metadata.dialogueTree || []); player.metadata.dialogueIndices = {}; - const parsedSubTree = parseDialogueTree(player, action.npcParticipants, action.subTree); + const parsedSubTree = parseDialogueTree(player, npcParticipants, action.subTree); player.metadata.dialogueTree = parsedSubTree; await runParsedDialogue(player, parsedSubTree, undefined, additionalOptions); player.metadata.dialogueIndices = originalIndices; player.metadata.dialogueTree = originalTree; - } else if(tag && dialogueAction.tag !== tag) { + } else if (tag && dialogueAction.tag !== tag) { const originalIndices = _.cloneDeep(player.metadata.dialogueIndices || {}); const originalTree = _.cloneDeep(player.metadata.dialogueTree || []); player.metadata.dialogueIndices = {}; - const parsedSubTree = parseDialogueTree(player, action.npcParticipants, action.subTree); + const parsedSubTree = parseDialogueTree(player, npcParticipants, action.subTree); player.metadata.dialogueTree = parsedSubTree; await runParsedDialogue(player, parsedSubTree, tag, additionalOptions); @@ -532,30 +575,38 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog } else { // Player or Npc dialogue. - if(tag === undefined || dialogueAction.tag === tag) { + if (tag === undefined || dialogueAction.tag === tag) { tag = undefined; - let npcId: number; + let npcId: number = -1; - if(dialogueAction.type === 'NPC') { + if (dialogueAction.type === 'NPC') { npcId = (dialogueAction as NpcDialogueAction).npcId; } + // TODO (Jameskmonger) not sure if this check is needed, added it when getting TypeScript types into strict mode + if (npcId === -1) { + throw new Error('No npc found for dialogue action.'); + } const actorDialogueAction = dialogueAction as ActorDialogueAction; const lines = actorDialogueAction.lines; - if(lines.length > 4) { - throw new Error(`Too many lines for actor dialogue! Dialogue has ${lines.length} lines but ` + - `the maximum is 4: ${JSON.stringify(lines)}`); + if (lines.length > 4) { + throw new Error(`Too many lines for actor dialogue! Dialogue has ${ lines.length } lines but ` + + `the maximum is 4: ${ JSON.stringify(lines) }`); } const animation = actorDialogueAction.animation; - if(dialogueAction.type === 'NPC') { + if (dialogueAction.type === 'NPC') { widgetId = npcWidgetIds[lines.length - 1]; - player.outgoingPackets.setWidgetNpcHead(widgetId, 0, npcId as number); - player.outgoingPackets.updateWidgetString(widgetId, 1, - filestore.configStore.npcStore.getNpc(npcId as number).name); + player.outgoingPackets.setWidgetNpcHead(widgetId, 0, npcId); + + const npcDetails = filestore.configStore.npcStore.getNpc(npcId); + + if (npcDetails && npcDetails.name) { + player.outgoingPackets.updateWidgetString(widgetId, 1, npcDetails.name); + } } else { widgetId = playerWidgetIds[lines.length - 1]; player.outgoingPackets.setWidgetPlayerHead(widgetId, 0); @@ -563,7 +614,7 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog } player.outgoingPackets.playWidgetAnimation(widgetId, 0, animation); - for(let i = 0; i < lines.length; i++) { + for (let i = 0; i < lines.length; i++) { player.outgoingPackets.updateWidgetString(widgetId, 2 + i, lines[i]); } @@ -571,10 +622,10 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog } - if(tag === undefined && widgetId) { + if (tag === undefined && widgetId !== -1) { const permanent = additionalOptions?.permanent || false; - if(permanent) { + if (permanent) { player.interfaceState.openChatOverlayWidget(widgetId); } else { player.interfaceState.openWidget(widgetId, { @@ -584,13 +635,13 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog const widgetClosedEvent = await player.interfaceState.widgetClosed('chatbox'); - if(widgetClosedEvent.data !== undefined) { - if(isOptions && typeof widgetClosedEvent.data === 'number') { + if (widgetClosedEvent.data !== undefined) { + if (isOptions && typeof widgetClosedEvent.data === 'number') { const optionsAction = dialogueAction as OptionsDialogueAction; const options = Object.keys(optionsAction.options); const trees = options.map(option => optionsAction.options[option]); const tree: ParsedDialogueTree = trees[widgetClosedEvent.data - 1]; - if(tree && tree.length !== 0) { + if (tree && tree.length !== 0) { await runParsedDialogue(player, tree, tag, additionalOptions); } } @@ -604,9 +655,9 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog async function runParsedDialogue(player: Player, dialogueTree: ParsedDialogueTree, tag?: string | undefined | false, additionalOptions?: AdditionalOptions): Promise { - for(let i = 0; i < dialogueTree.length; i++) { + for (let i = 0; i < dialogueTree.length; i++) { tag = await runDialogueAction(player, dialogueTree[i], tag, additionalOptions); - if(tag === false) { + if (tag === false) { break; } } @@ -618,12 +669,12 @@ export async function dialogue(participants: (Player | NpcParticipant)[], dialog additionalOptions?: AdditionalOptions): Promise { const player = participants.find(p => p instanceof Player) as Player; - if(!player) { + if (!player) { throw new Error('Player instance not provided to dialogue action.'); } let npcParticipants = participants.filter(p => !(p instanceof Player)) as NpcParticipant[]; - if(!npcParticipants) { + if (!npcParticipants) { npcParticipants = []; } @@ -635,7 +686,7 @@ export async function dialogue(participants: (Player | NpcParticipant)[], dialog await runParsedDialogue(player, parsedDialogueTree, undefined, additionalOptions); player.interfaceState.closeAllSlots(); return true; - } catch(error) { + } catch (error) { player.interfaceState.closeAllSlots(); logger.warn(error); return false; @@ -694,11 +745,11 @@ export interface ItemSelection { export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'MAKING', items: SelectableItem[]): Promise { let widgetId = 307; - if(type === 'MAKING') { - if(items.length === 1) { + if (type === 'MAKING') { + if (items.length === 1) { widgetId = 309; } else { - if(items.length > 5) { + if (items.length > 5) { throw new Error(`Too many items provided to the item selection action!`); } @@ -710,11 +761,11 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M childIds.forEach((childId, index) => { const itemInfo = items[index]; - if(itemInfo.offset === undefined) { + if (itemInfo.offset === undefined) { itemInfo.offset = -12; } - if(itemInfo.zoom === undefined) { + if (itemInfo.zoom === undefined) { itemInfo.zoom = 180; } @@ -735,7 +786,7 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M }); const interactionSub = player.dialogueInteractionEvent.subscribe(childId => { - if(!player.interfaceState.widgetOpen('chatbox', widgetId)) { + if (!player.interfaceState.widgetOpen('chatbox', widgetId)) { interactionSub.unsubscribe(); actionsSub.unsubscribe(); reject('Active Widget Mismatch'); @@ -746,7 +797,7 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M const choiceIndex = options.findIndex(arr => arr.indexOf(childId) !== -1); - if(choiceIndex === -1) { + if (choiceIndex === -1) { interactionSub.unsubscribe(); actionsSub.unsubscribe(); reject('Choice Index Not Found'); @@ -755,7 +806,7 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M const optionIndex = options[choiceIndex].indexOf(childId); - if(optionIndex === -1) { + if (optionIndex === -1) { interactionSub.unsubscribe(); actionsSub.unsubscribe(); reject('Option Index Not Found'); @@ -765,7 +816,7 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M const itemId = items[choiceIndex].itemId; let amount = itemSelectionDialogueAmounts[optionIndex]; - if(amount === 'X') { + if (amount === 'X') { actionsSub.unsubscribe(); player.outgoingPackets.showNumberInputDialogue(); @@ -780,7 +831,7 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M actionsSub.unsubscribe(); interactionSub.unsubscribe(); - if(input < 1 || input > 2147483647) { + if (input < 1 || input > 2147483647) { player.interfaceState.closeWidget('chatbox'); reject('Invalid User Amount Input'); } else { @@ -789,7 +840,7 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M } }); } else { - if(amount === 'All') { + if (amount === 'All') { amount = player.inventory.findAll(itemId).length; } diff --git a/src/engine/world/actor/index.ts b/src/engine/world/actor/index.ts new file mode 100644 index 000000000..6f77d870c --- /dev/null +++ b/src/engine/world/actor/index.ts @@ -0,0 +1,12 @@ +export * from './combat'; +export * from './dialogue'; +export * from './magic'; +export * from './pathfinding'; +export * from './prayer'; +export * from './skills'; +export * from './update-flags'; +export * from './walking-queue'; + +export * from './player'; +export * from './npc'; +export * from './actor'; diff --git a/src/game-engine/world/actor/magic.ts b/src/engine/world/actor/magic.ts similarity index 93% rename from src/game-engine/world/actor/magic.ts rename to src/engine/world/actor/magic.ts index ee72be89f..517bf9598 100644 --- a/src/game-engine/world/actor/magic.ts +++ b/src/engine/world/actor/magic.ts @@ -1,15 +1,15 @@ -export interface Magic { - Name: string; - ButtonID: number; - CoolDown: number; - BaseDamage: number; - EffectID: number; - DamageCalculation(): number; - - -} -export abstract class Magic { - - -} - +export interface Magic { + Name: string; + ButtonID: number; + CoolDown: number; + BaseDamage: number; + EffectID: number; + DamageCalculation(): number; + + +} +export abstract class Magic { + + +} + diff --git a/src/engine/world/actor/metadata.ts b/src/engine/world/actor/metadata.ts new file mode 100644 index 000000000..550b28103 --- /dev/null +++ b/src/engine/world/actor/metadata.ts @@ -0,0 +1,49 @@ +import { ConstructedRegion } from '../map'; +import { Position } from '../position'; +import { Actor } from './actor'; + +/** + * The definition of the metadata available on an {@link Actor}. + * + * You cannot guarantee that all of these properties will be present on an actor, + * so you should always check for their existence before using them. + * + * @author jameskmonger + */ +export type ActorMetadata = { + /** + * The custom constructed map region for this actor. + * + * TODO (jameskmonger) Should this live on Actor rather than on {@link Player}? I don't think NPCs can have a custom map. + */ + customMap: ConstructedRegion; + + /** + * The player's current target position. + * + * Used within the action pipeline. + */ + walkingTo: Position; + + /** + * The actor currently being followed by this actor. + */ + following: Actor; + + /** + * The actor which the local actor is facing towards. + */ + faceActor: Actor; + + /** + * Whether a walk action has cleared the actor which the local actor is facing towards. + * + * TODO (jameskmonger) does this belong on this metadata? + */ + faceActorClearedByWalking: boolean; + + /** + * Set to true if the actor is currently teleporting. + */ + teleporting: boolean; +}; diff --git a/src/game-engine/world/actor/npc/npc.ts b/src/engine/world/actor/npc.ts similarity index 74% rename from src/game-engine/world/actor/npc/npc.ts rename to src/engine/world/actor/npc.ts index 9a304a114..159b3c7cb 100644 --- a/src/game-engine/world/actor/npc/npc.ts +++ b/src/engine/world/actor/npc.ts @@ -1,28 +1,21 @@ -import { Actor } from '@engine/world/actor/actor'; import uuidv4 from 'uuid/v4'; -import { Position } from '@engine/world/position'; -import { filestore, world } from '@engine/game-server'; -import { directionData } from '@engine/world/direction'; -import { QuadtreeKey } from '@engine/world'; -import { findItem, findNpc } from '@engine/config'; -import { animationIds } from '@engine/world/config/animation-ids'; -import { DropTable, NpcCombatAnimations, NpcDetails } from '@engine/config/npc-config'; -import { SkillName } from '@engine/world/actor/skills'; -import { NpcSpawn } from '@engine/config/npc-spawn-config'; -import { MeleeCombatBehavior } from '../behaviors/melee-combat.behavior'; -import { forEach } from 'lodash'; -import { Behavior } from '../behaviors/behavior'; import EventEmitter from 'events'; -import { soundIds } from '../../config/sound-ids'; -import { Player } from '../player/player'; -import { itemIds } from '../../config/item-ids'; -import { logger } from '@runejs/core'; +import { filestore } from '@server/game/game-server'; +import { Position, directionData, QuadtreeKey, WorldInstance, activeWorld } from '@engine/world'; +import { findItem, findNpc, NpcCombatAnimations, NpcDetails, NpcSpawn } from '@engine/config'; +import { soundIds, animationIds } from '@engine/world/config'; + +import { Actor } from './actor'; +import { Player } from './player'; +import { SkillName } from './skills'; +import { logger } from '@runejs/common'; /** * Represents a non-player character within the game world. */ export class Npc extends Actor { + public readonly uuid: string; public readonly options: string[]; public readonly initialPosition: Position; @@ -39,31 +32,30 @@ export class Npc extends Actor { turnRight?: number; stand?: number; }; - public instanceId: string = null; //ToDo: this should either be calculated by the level or from a config public experienceValue: number = 10; public npcEvents: EventEmitter = new EventEmitter(); - private _name: string; private _combatLevel: number; private _movementRadius: number = 0; - private quadtreeKey: QuadtreeKey = null; + private quadtreeKey: QuadtreeKey | null = null; private _exists: boolean = true; private npcSpawn: NpcSpawn; private _initialized: boolean = false; - - - public constructor(npcDetails: NpcDetails | number, npcSpawn: NpcSpawn, instanceId: string = null) { - super(); + public constructor(npcDetails: NpcDetails | number, npcSpawn: NpcSpawn, instance: WorldInstance | null = null) { + super('npc'); this.key = npcSpawn.npcKey; this.uuid = uuidv4(); this.position = npcSpawn.spawnPosition.clone(); this.initialPosition = this.position.clone(); this.npcSpawn = npcSpawn; - this.instanceId = instanceId; + + if(instance) { + this.instance = instance; + } if(npcSpawn.movementRadius) { this._movementRadius = npcSpawn.movementRadius; @@ -78,12 +70,13 @@ export class Npc extends Actor { } else { this.id = npcDetails.gameId; this._combatLevel = npcDetails.combatLevel; - this.animations = npcDetails.combatAnimations; - this.options = npcDetails.options; + this.animations = npcDetails.combatAnimations || {}; + this.options = npcDetails.options || []; if(npcDetails.skills) { const skillNames = Object.keys(npcDetails.skills); - skillNames.forEach(skillName => this.skills.setLevel(skillName as SkillName, npcDetails.skills[skillName])); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + skillNames.forEach(skillName => this.skills.setLevel(skillName as SkillName, npcDetails.skills![skillName])); } } @@ -91,9 +84,10 @@ export class Npc extends Actor { if(cacheDetails) { // NPC not registered on the server, but exists in the game cache - use that for our info and assume it's // Not a combatant NPC since we have no useful combat information for it. - this._name = cacheDetails.name; + + this._name = cacheDetails.name || ''; this._combatLevel = cacheDetails.combatLevel; - this.options = cacheDetails.options; + this.options = cacheDetails.options || []; this.varbitId = cacheDetails.varbitId; this.settingId = cacheDetails.settingId; this.childrenIds = cacheDetails.childrenIds; @@ -107,13 +101,14 @@ export class Npc extends Actor { } else { this._name = 'Unknown'; } - // ToDo: this should be config based and not always melee (obviously) - this.Behaviors.push(new MeleeCombatBehavior()); + this.npcEvents.on('death', this.processDeath); } public async init(): Promise { - world.chunkManager.getChunkForWorldPosition(this.position).addNpc(this); + super.init(); + + activeWorld.chunkManager.getChunkForWorldPosition(this.position).addNpc(this); if(this.movementRadius > 0) { this.initiateRandomMovement(); @@ -134,53 +129,61 @@ export class Npc extends Actor { deathAnim = findNpc((defender as Npc).id)?.combatAnimations?.death || animationIds.death defender.playAnimation(deathAnim); - world.playLocationSound(deathPosition, soundIds.npc.human.maleDeath, 5); + activeWorld.playLocationSound(deathPosition, defender.instance.instanceId, soundIds.npc.human.maleDeath, 5); const npcDetails = findNpc((defender as Npc).id); - if(!npcDetails.dropTable) { + if(!npcDetails || !npcDetails.dropTable) { return; } if(assailant instanceof Player) { const itemDrops = calculateNpcDrops(assailant, npcDetails); itemDrops.forEach(drop => { - world.globalInstance.spawnWorldItem({ itemId: findItem(drop.itemKey).gameId, amount: drop.amount }, + const droppedItem = findItem(drop.itemKey); + + if (!droppedItem) { + logger.error(`Unable to find item with key: ${drop.itemKey}`); + return; + } + + if (!drop.amount) { + logger.error(`Unable to drop item with key: ${drop.itemKey} - no amount specified`); + return; + } + + activeWorld.globalInstance.spawnWorldItem({ itemId: droppedItem.gameId, amount: drop.amount }, deathPosition, { owner: assailant instanceof Player ? assailant : undefined, expires: 300 }); }) } }); - - } - public getAttackAnimation(): number { - let attackAnim = findNpc(this.id)?.combatAnimations?.attack || animationIds.combat.punch; - if(Array.isArray(attackAnim)) { - // NPC has multiple attack animations possible, pick a random one from the list to use - const idx = Math.floor(Math.random() * attackAnim.length); - attackAnim = attackAnim[idx]; - } - - return attackAnim; } - public getBlockAnimation(): number { - return findNpc(this.id)?.combatAnimations?.defend || animationIds.combat.armBlock; + public withinBounds(x: number, y: number): boolean { + return !(x > this.initialPosition.x + this.movementRadius || x < this.initialPosition.x - this.movementRadius + || y > this.initialPosition.y + this.movementRadius || y < this.initialPosition.y - this.movementRadius); } public kill(respawn: boolean = true): void { + this.destroy(); - world.chunkManager.getChunkForWorldPosition(this.position).removeNpc(this); + activeWorld.chunkManager.getChunkForWorldPosition(this.position).removeNpc(this); clearInterval(this.randomMovementInterval); - world.deregisterNpc(this); + activeWorld.deregisterNpc(this); if(respawn) { - world.scheduleNpcRespawn(new Npc(findNpc(this.id), this.npcSpawn)); + const npcDetails = findNpc(this.id); + + if(!npcDetails) { + return; + } + + activeWorld.scheduleNpcRespawn(new Npc(npcDetails, this.npcSpawn)); } } public async tick(): Promise { - for (let i = 0; i < this.Behaviors.length; i++) { - this.Behaviors[i].tick(); - } + super.tick(); + return new Promise(resolve => { this.walkingQueue.process(); resolve(); @@ -206,7 +209,7 @@ export class Npc extends Actor { * Whether or not the Npc can currently move. */ public canMove(): boolean { - if(this.metadata.following || this.metadata.tailing) { + if(this.metadata.following) { return false; } return this.updateFlags.faceActor === undefined && this.updateFlags.animation === undefined; @@ -218,7 +221,7 @@ export class Npc extends Actor { * @param volume The volume to play the sound at. */ public playSound(soundId: number, volume: number): void { - world.playLocationSound(this.position, soundId, volume); + activeWorld.playLocationSound(this.position, this.instance.instanceId, soundId, volume); } /** @@ -226,7 +229,14 @@ export class Npc extends Actor { * @param npcKey The unique string key of the Npc to transform into. */ public transformInto(npcKey: string): void { - this.id = findNpc(npcKey).gameId; + const npcDetails = findNpc(npcKey); + + if(!npcDetails) { + logger.error(`Unable to find npc with key: ${npcKey} for transformation.`); + return; + } + + this.id = npcDetails.gameId; this.updateFlags.appearanceUpdateRequired = true; } @@ -251,11 +261,11 @@ export class Npc extends Actor { super.position = position; if(this.quadtreeKey !== null) { - world.npcTree.remove(this.quadtreeKey); + activeWorld.npcTree.remove(this.quadtreeKey); } this.quadtreeKey = { x: position.x, y: position.y, actor: this }; - world.npcTree.push(this.quadtreeKey); + activeWorld.npcTree.push(this.quadtreeKey); } public get position(): Position { @@ -285,6 +295,10 @@ export class Npc extends Actor { public get initialized(): boolean { return this._initialized; } + + public get instanceId(): string | null { + return this.instance?.instanceId ?? null; + } } /** diff --git a/src/game-engine/world/actor/pathfinding.ts b/src/engine/world/actor/pathfinding.ts similarity index 90% rename from src/game-engine/world/actor/pathfinding.ts rename to src/engine/world/actor/pathfinding.ts index d47178243..422ba8b57 100644 --- a/src/game-engine/world/actor/pathfinding.ts +++ b/src/engine/world/actor/pathfinding.ts @@ -1,22 +1,26 @@ -import { world } from '@engine/game-server'; import { Actor } from '@engine/world/actor/actor'; import { Position } from '../position'; import { Chunk } from '@engine/world/map/chunk'; import { Player } from '@engine/world/actor/player/player'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; import { WorldInstance } from '@engine/world/instances'; import { Tile } from '@engine/world/map/chunk-manager'; +import { activeWorld } from '@engine/world'; class Point { - private _parent: Point = null; + private _parent: Point | null = null; private _cost: number = 0; public constructor(private readonly _x: number, private readonly _y: number) { } - public equals(point: Point): boolean { + public equals(point: Point | null): boolean { + if (point === null) { + return false; + } + if(this._cost === point._cost) { if(this._parent === null && point._parent !== null) { return false; @@ -38,11 +42,11 @@ class Point { return this._y; } - public get parent(): Point { + public get parent(): Point | null { return this._parent; } - public set parent(value: Point) { + public set parent(value: Point | null) { this._parent = value; } @@ -85,8 +89,8 @@ export class Pathfinding { const walkingQueue = this.actor.walkingQueue; - if(this.actor instanceof Player) { - this.actor.walkingTo = null; + if(this.actor.metadata.walkingTo) { + delete this.actor.metadata.walkingTo; } walkingQueue.clear(); @@ -104,12 +108,6 @@ export class Pathfinding { } } - public async path(destination: Position, searchRadius: number = 8): Promise { - const tileMap = await this.createTileMap(searchRadius); - - return null; - } - public createTileMap(searchRadius: number = 8): { [key: string]: Tile } { const position = this.actor.position; const lowestX = position.x - searchRadius; @@ -117,10 +115,10 @@ export class Pathfinding { const highestX = position.x + searchRadius; const highestY = position.y + searchRadius; - const tiles = []; + const tiles: Tile[] = []; for(let x = lowestX; x < highestX; x++) { for(let y = lowestY; y < highestY; y++) { - tiles.push(world.chunkManager.getTile(new Position(x, y, this.actor.position.level))); + tiles.push(activeWorld.chunkManager.getTile(new Position(x, y, this.actor.position.level))); } } @@ -129,7 +127,7 @@ export class Pathfinding { ); } - public pathTo(destinationX: number, destinationY: number, searchRadius: number = 16): Point[] { + public pathTo(destinationX: number, destinationY: number, searchRadius: number = 16): Point[] | null { const position = this.actor.position; const lowestX = position.x - searchRadius; const lowestY = position.y - searchRadius; @@ -169,12 +167,14 @@ export class Pathfinding { return null; } - this.currentPoint = this.calculateBestPoint(); + const bestPoint = this.calculateBestPoint(); - if(!this.currentPoint || this.currentPoint.equals(this.points[destinationIndexX][destinationIndexY])) { + if(!bestPoint || bestPoint.equals(this.points[destinationIndexX][destinationIndexY])) { break; } + this.currentPoint = bestPoint; + this.openPoints.delete(this.currentPoint); this.closedPoints.add(this.currentPoint); @@ -247,7 +247,7 @@ export class Pathfinding { // build path const path: Point[] = []; - let point = destinationPoint; + let point: Point | null = destinationPoint; let iterations = 0; do { @@ -272,8 +272,8 @@ export class Pathfinding { } public canMoveTo(origin: Position, destination: Position): boolean { - const destinationChunk: Chunk = world.chunkManager.getChunkForWorldPosition(destination); - const tile: Tile = world.chunkManager.getTile(destination); + const destinationChunk: Chunk = activeWorld.chunkManager.getChunkForWorldPosition(destination); + const tile: Tile = activeWorld.chunkManager.getTile(destination); if(tile?.blocked) { return false; @@ -375,11 +375,11 @@ export class Pathfinding { public findLocalCornerChunk(cornerX: number, cornerY: number, origin: Position): { localX: number, localY: number, chunk: Chunk } { const cornerPosition: Position = new Position(cornerX, cornerY, origin.level + 1); - let cornerChunk: Chunk = world.chunkManager.getChunkForWorldPosition(cornerPosition); - const tileAbove: Tile = world.chunkManager.getTile(cornerPosition); + let cornerChunk: Chunk = activeWorld.chunkManager.getChunkForWorldPosition(cornerPosition); + const tileAbove: Tile = activeWorld.chunkManager.getTile(cornerPosition); if(!tileAbove?.bridge) { cornerPosition.level = cornerPosition.level - 1; - cornerChunk = world.chunkManager.getChunkForWorldPosition(cornerPosition); + cornerChunk = activeWorld.chunkManager.getChunkForWorldPosition(cornerPosition); } const localX: number = cornerX - cornerChunk.collisionMap.insetX; const localY: number = cornerY - cornerChunk.collisionMap.insetY; @@ -412,8 +412,8 @@ export class Pathfinding { return (Math.abs(deltaX) + Math.abs(deltaY)) * 10; } - private calculateBestPoint(): Point { - let bestPoint: Point = null; + private calculateBestPoint(): Point | null { + let bestPoint: Point | null = null; this.openPoints.forEach(point => { if(!bestPoint) { @@ -427,7 +427,7 @@ export class Pathfinding { } private canPathNSEW(position: Position, i: number): boolean { - const chunk = world.chunkManager.getChunkForWorldPosition(position); + const chunk = activeWorld.chunkManager.getChunkForWorldPosition(position); const destinationLocalX: number = position.x - chunk.collisionMap.insetX; const destinationLocalY: number = position.y - chunk.collisionMap.insetY; return this.movementPermitted(this.instance, chunk, destinationLocalX, destinationLocalY, i); @@ -435,7 +435,7 @@ export class Pathfinding { private canPathDiagonally(originX: number, originY: number, position: Position, offsetX: number, offsetY: number, destMask: number, cornerMask1: number, cornerMask2: number): boolean { - const chunk = world.chunkManager.getChunkForWorldPosition(position); + const chunk = activeWorld.chunkManager.getChunkForWorldPosition(position); const destinationLocalX: number = position.x - chunk.collisionMap.insetX; const destinationLocalY: number = position.y - chunk.collisionMap.insetY; return this.diagonalMovementPermitted(this.instance, position, chunk, destinationLocalX, destinationLocalY, @@ -443,7 +443,7 @@ export class Pathfinding { } private get instance(): WorldInstance { - return this.actor instanceof Player ? this.actor.instance : world.globalInstance; + return this.actor instanceof Player ? this.actor.instance : activeWorld.globalInstance; } } diff --git a/src/game-engine/world/actor/player/achievements.ts b/src/engine/world/actor/player/achievements.ts similarity index 96% rename from src/game-engine/world/actor/player/achievements.ts rename to src/engine/world/actor/player/achievements.ts index bd477a046..211583266 100644 --- a/src/game-engine/world/actor/player/achievements.ts +++ b/src/engine/world/actor/player/achievements.ts @@ -1,5 +1,5 @@ import { Player } from '@engine/world/actor/player/player'; -import { serverConfig } from '@engine/game-server'; +import { serverConfig } from '@server/game/game-server'; import { gfxIds } from '@engine/world/config/gfx-ids'; export const achievementSeries = { @@ -43,7 +43,7 @@ export const Achievements: { [key: string]: Achievement } = { export function giveAchievement(achievement: Achievement, player: Player): boolean { if(!serverConfig.giveAchievements) { - return; + return false; } if(hasAchievement(achievement, player)) { diff --git a/src/game-engine/world/actor/player/attack.ts b/src/engine/world/actor/player/attack.ts similarity index 98% rename from src/game-engine/world/actor/player/attack.ts rename to src/engine/world/actor/player/attack.ts index 63ffad08b..25fd0e5d1 100644 --- a/src/game-engine/world/actor/player/attack.ts +++ b/src/engine/world/actor/player/attack.ts @@ -6,13 +6,13 @@ export class Attack { defenseRoll: number = 0; hitChance: number =0; damage: number =0; - maximumHit: number; + maximumHit: number; } export enum AttackDamageType { - Stab, - Slash, - Crush, - Magic, - Range + Stab, + Slash, + Crush, + Magic, + Range } \ No newline at end of file diff --git a/src/game-engine/world/actor/player/cutscenes.ts b/src/engine/world/actor/player/cutscenes.ts similarity index 100% rename from src/game-engine/world/actor/player/cutscenes.ts rename to src/engine/world/actor/player/cutscenes.ts diff --git a/src/game-engine/world/actor/player/dialogue-action.ts b/src/engine/world/actor/player/dialogue-action.ts similarity index 84% rename from src/game-engine/world/actor/player/dialogue-action.ts rename to src/engine/world/actor/player/dialogue-action.ts index cbb981a44..542215f80 100644 --- a/src/game-engine/world/actor/player/dialogue-action.ts +++ b/src/engine/world/actor/player/dialogue-action.ts @@ -1,6 +1,7 @@ import { Player } from '@engine/world/actor/player/player'; -import { filestore } from '@engine/game-server'; -import { Npc } from '@engine/world/actor/npc/npc'; +import { filestore } from '@server/game/game-server'; +import { Npc } from '@engine/world/actor/npc'; +import { logger } from '@runejs/common'; export const dialogueWidgetIds = { PLAYER: [ 64, 65, 66, 67 ], @@ -68,7 +69,7 @@ export interface DialogueOptions { // @DEPRECATED export class DialogueAction { - private _action: number = null; + private _action: number | null = null; public constructor(private readonly p: Player) { } @@ -115,9 +116,21 @@ export class DialogueAction { } if(options.type === 'NPC') { - this.p.outgoingPackets.setWidgetNpcHead(widgetId, 0, options.npc); - this.p.outgoingPackets.updateWidgetString(widgetId, 1, - filestore.configStore.npcStore.getNpc(options.npc).name); + const npc = options.npc; + + if (npc === undefined) { + // TODO (Jameskmonger) how can this error be handled in a better way? + throw new Error('NPC not supplied.'); + } + + const cacheNpc = filestore.configStore.npcStore.getNpc(npc); + + if (!cacheNpc) { + throw new Error(`NPC ${npc} not found in cache.`); + } + + this.p.outgoingPackets.setWidgetNpcHead(widgetId, 0, npc); + this.p.outgoingPackets.updateWidgetString(widgetId, 1, cacheNpc.name || 'Unknown'); } else if(options.type === 'PLAYER') { this.p.outgoingPackets.setWidgetPlayerHead(widgetId, 0); this.p.outgoingPackets.updateWidgetString(widgetId, 1, this.p.username); @@ -126,7 +139,7 @@ export class DialogueAction { this.p.outgoingPackets.playWidgetAnimation(widgetId, 0, options.emote); textOffset = 2; } else if(options.type === 'OPTIONS') { - this.p.outgoingPackets.updateWidgetString(widgetId, 0, options.title); + this.p.outgoingPackets.updateWidgetString(widgetId, 0, options.title || 'No Title'); textOffset = 1; } else if(options.type === 'TEXT') { textOffset = 0; @@ -142,7 +155,7 @@ export class DialogueAction { }) const sub = this.p.interfaceState.closed.subscribe(action => { sub.unsubscribe(); - this._action = action; + this._action = action?.data ?? null; resolve(this); }); }); @@ -152,11 +165,11 @@ export class DialogueAction { this.p.outgoingPackets.closeActiveWidgets(); } - public get action(): number { + public get action(): number | null { return this._action; } - public set action(value: number) { + public set action(value: number | null) { this._action = value; } } diff --git a/src/engine/world/actor/player/index.ts b/src/engine/world/actor/player/index.ts new file mode 100644 index 000000000..a3a79c3bc --- /dev/null +++ b/src/engine/world/actor/player/index.ts @@ -0,0 +1,9 @@ +export * from './sync'; +export * from './achievements'; +export * from './attack'; +export * from './cutscenes'; +export * from './model'; +export * from './player'; +export * from './player-data'; +export * from './private-messaging'; +export * from './quest'; diff --git a/src/engine/world/actor/player/metadata.ts b/src/engine/world/actor/player/metadata.ts new file mode 100644 index 000000000..e4c8c4935 --- /dev/null +++ b/src/engine/world/actor/player/metadata.ts @@ -0,0 +1,110 @@ +import { Subject, Subscription } from 'rxjs'; +import { Chunk } from '@engine/world/map'; +import { Position } from '@engine/world/position'; +import { LandscapeObject } from '@runejs/filestore'; + +/** + * The definition of the metadata directly available on a {@link Player}. + * + * This is a subset of the metadata available on an {@link Actor}. See {@link ActorMetadata} for more information. + * + * You cannot guarantee that all of these properties will be present on an actor, + * so you should always check for their existence before using them. + * + * @author jameskmonger + */ +export type PlayerMetadata = { + /** + * The player's client configuration options (varps). + */ + configs: number[]; + + /** + * The player's current and previous chunks. + */ + updateChunk: { + oldChunk: Chunk; + newChunk: Chunk; + }; + + /** + * The player's last position before teleporting. + */ + lastPosition: Position; + + /** + * Used to prevent the `object_interaction` pipe from running. + * + * TODO (jameskmonger) We should probably deprecate this, it seems like it's already been + * replaced by the `busy` property which is itself deprecated. This is only + * used in Goblin Diplomacy. + */ + blockObjectInteractions: boolean; + + /** + * The player's currently open shop. + * + * TODO (jameskmonger) This is currently an instance of `Shop`. We shouldn't be storing whole instances of classes in the metadata. + */ + lastOpenedShop: any; + + /** + * A subscription to the player's "widget closed" events. + * + * Used to remove a player from a shop when they close the shop's widget. + */ + shopCloseListener: Subscription; + + /** + * Allows listening to a player clicking on the tab at the specified index. + * + * The `event` property is a `Subject` that will emit a `boolean` value when the player clicks on the tab. + * + * TODO (jameskmonger) This is only used in Goblin Diplomacy. It is only present when the player is taking part + * in Goblin Displomacy. + */ + tabClickEvent: { + tabIndex: number; + event: Subject; + }; + + /** + * Used to process dialogue trees. + */ + dialogueIndices: Record; + + /** + * The player's current dialogue tree. + * + * This is a `ParsedDialogueTree` type, but that type is not exported. + */ + dialogueTree: any; + + /** + * A list of custom landscape objects that have been spawned by the player. + * + * Initialised by, and used by, the `spawn-scenery` command. + */ + spawnedScenery: LandscapeObject[]; + + /** + * The last custom landscape object that was spawned by the player. + * + * Used to provide `undo` functionality to the `spawn-scenery` command. + */ + lastSpawnedScenery: LandscapeObject; + + /** + * The timestamp of the last time the player lit a fire. + * + * Used to prevent the player from lighting fires too quickly. + * + * TODO (jameskmonger) this should not be using Dates for timing and will be converted in the new task system + */ + lastFire: number; + + /** + * The ID of the player's currently open skill guide. + */ + activeSkillGuide: number; +}; diff --git a/src/game-engine/world/actor/player/model.ts b/src/engine/world/actor/player/model.ts similarity index 100% rename from src/game-engine/world/actor/player/model.ts rename to src/engine/world/actor/player/model.ts diff --git a/src/game-engine/world/actor/player/player-data.ts b/src/engine/world/actor/player/player-data.ts similarity index 94% rename from src/game-engine/world/actor/player/player-data.ts rename to src/engine/world/actor/player/player-data.ts index d3c24d501..18c95b7ed 100644 --- a/src/game-engine/world/actor/player/player-data.ts +++ b/src/engine/world/actor/player/player-data.ts @@ -1,12 +1,12 @@ import { Item } from '@engine/world/items/item'; import { existsSync, readFileSync, writeFileSync } from 'fs'; import { join } from 'path'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; import { Player } from './player'; import { SkillValue } from '@engine/world/actor/skills'; import { hasValueNotNull } from '@engine/util/data'; import { PlayerQuest } from '@engine/config/quest-config'; -import { MusicPlayerLoopMode, MusicPlayerMode } from '@plugins/music/music-tab.plugin'; +import { MusicPlayerLoopMode, MusicPlayerMode } from '@engine/world/sound'; export interface Appearance { gender: number; @@ -59,9 +59,9 @@ export interface PlayerSave { address: string; }; appearance: Appearance; - inventory: Item[]; - bank: Item[]; - equipment: Item[]; + inventory: (Item | null)[]; + bank: (Item | null)[]; + equipment: (Item | null)[]; skills: SkillValue[]; settings: PlayerSettings; savedMetadata: { [key: string]: any }; @@ -157,7 +157,7 @@ export function playerExists(username: string): boolean { return existsSync(filePath); } -export function loadPlayerSave(username: string): PlayerSave { +export function loadPlayerSave(username: string): PlayerSave | null { const fileName = username.toLowerCase() + '.json'; const filePath = join('data/saves', fileName); diff --git a/src/game-engine/world/actor/player/player.ts b/src/engine/world/actor/player/player.ts similarity index 78% rename from src/game-engine/world/actor/player/player.ts rename to src/engine/world/actor/player/player.ts index 5af76aa13..055b4849d 100644 --- a/src/game-engine/world/actor/player/player.ts +++ b/src/engine/world/actor/player/player.ts @@ -1,12 +1,28 @@ import { AddressInfo, Socket } from 'net'; -import { OutboundPackets } from '@engine/net/outbound-packets'; -import { Isaac } from '@engine/net/isaac'; -import { PlayerSyncTask } from './sync/player-sync-task'; -import { Actor } from '../actor'; -import { Position } from '@engine/world/position'; -import { filestore, actionHookMap, serverConfig, world, questMap } from '@engine/game-server'; -import { logger } from '@runejs/core'; import uuidv4 from 'uuid/v4'; +import { Subject } from 'rxjs'; +import EventEmitter from 'events'; + +import { logger } from '@runejs/common'; + +import { filestore, serverConfig } from '@server/game'; +import { + findMusicTrack, findNpc, findSongIdByRegionId, musicRegions, equipmentIndex, + EquipmentSlot, getEquipmentSlot, ItemDetails, findItem, findQuest, + npcIdMap, widgets, NpcDetails, PlayerQuest, QuestKey, itemMap +} from '@engine/config'; +import { daysSinceLastLogin, colors, hexToRgb, rgbTo16Bit,getVarbitMorphIndex } from '@engine/util'; +import { OutboundPacketHandler, Isaac } from '@engine/net'; +import { actionHookMap, questMap } from '@engine/plugins'; + +import { Position, QuadtreeKey, TileModifications, activeWorld, WorldInstance } from '@engine/world'; +import { PlayerWidget, widgetScripts, itemIds, animationIds } from '@engine/world/config'; +import { ContainerUpdateEvent, getItemFromContainer, ItemContainer, Item } from '@engine/world/items'; +import { Chunk, ChunkUpdateItem } from '@engine/world/map'; +import { PlayerCommandActionHook, regionChangeActionFactory } from '@engine/action'; +import { MusicPlayerMode } from '@engine/world/sound'; + +import { Actor } from '../actor'; import { Appearance, defaultAppearance, @@ -17,52 +33,20 @@ import { PlayerSettings, savePlayerData } from './player-data'; -import { PlayerWidget, widgetScripts } from '../../config/widget'; -import { ContainerUpdateEvent, getItemFromContainer, ItemContainer } from '../../items/item-container'; -import { Item } from '../../items/item'; -import { Npc } from '../npc/npc'; -import { NpcSyncTask } from './sync/npc-sync-task'; -import { Subject } from 'rxjs'; -import { Chunk, ChunkUpdateItem } from '@engine/world/map/chunk'; -import { QuadtreeKey } from '@engine/world'; -import { daysSinceLastLogin } from '@engine/util/time'; -import { itemIds } from '@engine/world/config/item-ids'; -import { colors, hexToRgb, rgbTo16Bit } from '@engine/util/colors'; -import { PlayerCommandActionHook } from '@engine/world/action/player-command.action'; -import { updateBonusStrings } from '@plugins/items/equipment/equipment-stats.plugin'; -import { findMusicTrack, findNpc, findSongIdByRegionId, musicRegions } from '@engine/config/index'; +import { Cutscene } from './cutscenes'; +import { InterfaceState } from '@engine/interface'; +import { Quest } from './quest'; +import { SendMessageOptions } from './model'; +import { PlayerSyncTask, NpcSyncTask } from './sync'; +import { dialogue } from '../dialogue'; +import { Npc } from '../npc'; +import { SkillName } from '../skills'; +import { PlayerMetadata } from './metadata'; -import { - DefensiveBonuses, - equipmentIndex, - EquipmentSlot, - getEquipmentSlot, - ItemDetails, - OffensiveBonuses, - SkillBonuses -} from '@engine/config/item-config'; -import { findItem, findQuest, npcIdMap, widgets } from '@engine/config'; -import { NpcDetails } from '@engine/config/npc-config'; -import { animationIds } from '@engine/world/config/animation-ids'; -import { combatStyles } from '@engine/world/actor/combat'; -import { TileModifications, WorldInstance } from '@engine/world/instances'; -import { Cutscene } from '@engine/world/actor/player/cutscenes'; -import { InterfaceState } from '@engine/world/actor/player/interface-state'; -import { dialogue } from '@engine/world/actor/dialogue'; -import { PlayerQuest, QuestKey } from '@engine/config/quest-config'; -import { Quest } from '@engine/world/actor/player/quest'; -import { regionChangeActionFactory } from '@engine/world/action/region-change.action'; -import { MusicPlayerMode } from '@plugins/music/music-tab.plugin'; -import { getVarbitMorphIndex } from '@engine/util/varbits'; -import { SendMessageOptions } from '@engine/world/actor/player/model'; -import { AutoAttackBehavior } from '../behaviors/auto-attack.behavior'; -import { EventEmitter } from 'events'; -import { AttackDamageType } from './attack'; -import { EffectType } from '../effect'; export const playerOptions: { option: string, index: number, placement: 'TOP' | 'BOTTOM' }[] = [ { - option: 'Yeet', + option: 'Trade with', index: 1, placement: 'TOP' }, @@ -73,12 +57,12 @@ export const playerOptions: { option: string, index: number, placement: 'TOP' | } ]; -export const defaultPlayerTabWidgets = [ +export const defaultPlayerTabWidgets = () => ([ -1, widgets.skillsTab, widgets.questTab, widgets.inventory.widgetId, widgets.equipment.widgetId, widgets.prayerTab, widgets.standardSpellbookTab, null, widgets.friendsList, widgets.ignoreList, widgets.logoutTab, widgets.settingsTab, widgets.emotesTab, widgets.musicPlayerTab -]; +]); export enum SidebarTab { COMBAT, @@ -107,6 +91,7 @@ export enum Rights { * A player character within the game world. */ export class Player extends Actor { + public readonly clientUuid: number; public readonly username: string; public readonly passwordHash: string; @@ -126,33 +111,39 @@ export class Player extends Actor { public achievements: string[] = []; public friendsList: string[] = []; public ignoreList: string[] = []; - public cutscene: Cutscene = null; + public cutscene: Cutscene | null = null; public playerEvents: EventEmitter = new EventEmitter(); - + /** + * Override the Actor's `metadata` property to provide a more specific type. + * + * You cannot guarantee that this will be populated with data, so you should always check for the existence of the + * metadata you are looking for before using it. + * + * @author jameskmonger + */ + public readonly metadata: (Actor['metadata'] & Partial) = {}; private readonly _socket: Socket; private readonly _inCipher: Isaac; private readonly _outCipher: Isaac; - private readonly _outgoingPackets: OutboundPackets; + private readonly _outgoingPackets: OutboundPacketHandler; private readonly _equipment: ItemContainer; private _rights: Rights; - private loggedIn: boolean; private _loginDate: Date; private _lastAddress: string; private firstTimePlayer: boolean; private _appearance: Appearance; private queuedWidgets: PlayerWidget[]; - private _bonuses: { offensive: OffensiveBonuses, defensive: DefensiveBonuses, skill: SkillBonuses }; private _carryWeight: number; private _settings: PlayerSettings; private _nearbyChunks: Chunk[]; - private quadtreeKey: QuadtreeKey = null; + private quadtreeKey: QuadtreeKey | null = null; private privateMessageIndex: number = 1; public constructor(socket: Socket, inCipher: Isaac, outCipher: Isaac, clientUuid: number, username: string, password: string, isLowDetail: boolean) { - super(); + super('player'); this._socket = socket; this._inCipher = inCipher; @@ -162,7 +153,7 @@ export class Player extends Actor { this.passwordHash = password; this._rights = Rights.ADMIN; this.isLowDetail = isLowDetail; - this._outgoingPackets = new OutboundPackets(this); + this._outgoingPackets = new OutboundPacketHandler(this); this.playerUpdateTask = new PlayerSyncTask(this); this.npcUpdateTask = new NpcSyncTask(this); this.trackedPlayers = []; @@ -180,18 +171,19 @@ export class Player extends Actor { } public async init(): Promise { - this.loggedIn = true; + super.init(); + this.updateFlags.mapRegionUpdateRequired = true; this.updateFlags.appearanceUpdateRequired = true; - const playerChunk = world.chunkManager.getChunkForWorldPosition(this.position); + const playerChunk = activeWorld.chunkManager.getChunkForWorldPosition(this.position); playerChunk.addPlayer(this); this.outgoingPackets.updateCurrentMapChunk(); this.outgoingPackets.chatboxMessage('Welcome to RuneJS.'); this.skills.values.forEach((skill, index) => - this.outgoingPackets.updateSkill(index, skill.level, skill.exp)); + this.outgoingPackets.updateSkill(index, this.skills.getLevel(index), skill.exp)); this.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, this.inventory); this.outgoingPackets.sendUpdateAllWidgetItems(widgets.equipment, this.equipment); @@ -274,20 +266,18 @@ export class Player extends Actor { await this.actionPipeline.call('player_init', { player: this }); - world.spawnWorldItems(this); + activeWorld.spawnWorldItems(this); if(!this.metadata.customMap) { this.chunkChanged(playerChunk); } - this.Behaviors.push(new AutoAttackBehavior()); - this.outgoingPackets.flushQueue(); logger.info(`${this.username}:${this.worldIndex} has logged in.`); } public logout(): void { - if(!this.loggedIn) { + if(!this.active) { return; } @@ -295,19 +285,26 @@ export class Player extends Actor { this.position.level = 0; } - world.playerTree.remove(this.quadtreeKey); + if (this.quadtreeKey) { + activeWorld.playerTree.remove(this.quadtreeKey); + } else { + // TODO (Jameskmonger) remove this log if it isn't a problem state + logger.warn(`Player ${this.username} has no quadtree key on logout.`); + } + this.save(); + this.destroy(); + this.actionsCancelled.complete(); this.walkingQueue.movementEvent.complete(); this.walkingQueue.movementQueued.complete(); this.actionPipeline.shutdown(); this.outgoingPackets.logout(); this.instance = null; - world.chunkManager.getChunkForWorldPosition(this.position).removePlayer(this); - world.deregisterPlayer(this); + activeWorld.chunkManager.getChunkForWorldPosition(this.position).removePlayer(this); + activeWorld.deregisterPlayer(this); - this.loggedIn = false; logger.info(`${this.username} has logged out.`); } @@ -315,28 +312,6 @@ export class Player extends Actor { savePlayerData(this); } - public getAttackAnimation(): number { - let combatStyle = [ 'unarmed', 0 ]; - - if(this.savedMetadata.combatStyle) { - combatStyle = this.savedMetadata.combatStyle; - } - - let attackAnim = combatStyles[combatStyle[0]][combatStyle[1]]?.anim || animationIds.combat.punch; - - if(Array.isArray(attackAnim)) { - // Player has multiple attack animations possible, pick a random one from the list to use - const idx = Math.floor(Math.random() * attackAnim.length); - attackAnim = attackAnim[idx]; - } - - return animationIds.combat[attackAnim] || animationIds.combat.kick; - } - - public getBlockAnimation(): number { - return animationIds.combat.armBlock; // @TODO - } - public privateMessageReceived(fromPlayer: Player, messageBytes: number[]): void { this.outgoingPackets.sendPrivateMessage(this.privateMessageIndex++, fromPlayer, messageBytes); } @@ -392,7 +367,7 @@ export class Player extends Actor { * @param chunk The player's new active map chunk. */ public chunkChanged(chunk: Chunk): void { - const nearbyChunks = world.chunkManager.getSurroundingChunks(chunk); + const nearbyChunks = activeWorld.chunkManager.getSurroundingChunks(chunk); if(this._nearbyChunks.length === 0) { this.sendChunkUpdates(nearbyChunks); } else { @@ -403,15 +378,18 @@ export class Player extends Actor { } public async tick(): Promise { - for (let i = 0; i < this.Behaviors.length; i++) { - this.Behaviors[i].tick(); - } + super.tick(); + return new Promise(resolve => { this.walkingQueue.process(); if(this.updateFlags.mapRegionUpdateRequired) { if(this.position.x >= 6400) { // Custom map drawing area is anywhere x >= 6400 on the map - this.outgoingPackets.constructMapRegion(this.metadata.customMap); + if (this.metadata.customMap) { + this.outgoingPackets.constructMapRegion(this.metadata.customMap); + } else { + logger.warn(`Player ${this.username} is in custom map area but has no custom map set.`); + } } else { this.outgoingPackets.updateCurrentMapChunk(); } @@ -431,16 +409,16 @@ export class Player extends Actor { this.outgoingPackets.flushQueue(); - if(this.metadata['updateChunk']) { - const { newChunk, oldChunk } = this.metadata['updateChunk']; + if(this.metadata.updateChunk) { + const { newChunk, oldChunk } = this.metadata.updateChunk; oldChunk.removePlayer(this); newChunk.addPlayer(this); this.chunkChanged(newChunk); - this.metadata['updateChunk'] = null; + this.metadata.updateChunk = undefined; } - if(this.metadata['teleporting']) { - this.metadata['teleporting'] = null; + if(this.metadata.teleporting) { + this.metadata.teleporting = undefined; } resolve(); @@ -475,13 +453,32 @@ export class Player extends Actor { return playerQuest; } + /** + * Checks if the player has unlocked the required stage of a quest + * @param questId The ID of the quest to find the player's status on. + * @param minimumStage The minimum quest stage required, defaults to completed + * @return boolean if the player has reached the required stage, if the quest does not exist it defaults to true + */ + public hasQuestRequirement(questId: string, minimumStage: QuestKey = 'complete'): boolean { + if(!questMap[questId]) { + logger.warn(`Quest data not found for ${questId}`); + return true; + } + let playerQuest = this.quests.find(quest => quest.questId === questId); + if(!playerQuest) { + playerQuest = new PlayerQuest(questId); + this.quests.push(playerQuest); + } + return playerQuest.progress === minimumStage || playerQuest.progress >= minimumStage; + } + /** * Sets a player's quest progress to the specified value. * @param questId The ID of the quest to set the progress of. * @param progress The progress to set the quest to. */ public setQuestProgress(questId: string, progress: QuestKey): void { - const questData: Quest = findQuest(questId); + const questData = findQuest(questId); if(!questData) { logger.warn(`Quest data not found for ${questId}`); @@ -519,8 +516,13 @@ export class Player extends Actor { } if(questData.onComplete.questCompleteWidget.itemId) { - this.outgoingPackets.updateWidgetModel1(widgets.questReward, 3, - filestore.configStore.itemStore.getItem(questData.onComplete.questCompleteWidget.itemId)?.model2d?.widgetModel); + const cacheItemData = filestore.configStore.itemStore.getItem(questData.onComplete.questCompleteWidget.itemId); + + if (cacheItemData && cacheItemData.model2d.widgetModel) { + this.outgoingPackets.updateWidgetModel1(widgets.questReward, 3, cacheItemData.model2d.widgetModel); + } + + } else if(questData.onComplete.questCompleteWidget.modelId) { this.outgoingPackets.updateWidgetModel1(widgets.questReward, 3, questData.onComplete.questCompleteWidget.modelId); } @@ -581,9 +583,15 @@ export class Player extends Actor { * @param songId The id of the song to play. */ public playSong(songId: number): void { + const musicTrack = findMusicTrack(songId); + if(!musicTrack) { + logger.warn(`Music track not found for id ${songId}`); + return; + } + this.modifyWidget(widgets.musicPlayerTab, { childId: 177, - text: findMusicTrack(songId).songName, + text: musicTrack.songName, textColor: colors.green }); this.savedMetadata['currentSongIdPlaying'] = songId; @@ -617,9 +625,9 @@ export class Player extends Actor { * @returns A Promise that resolves when the player has clicked the "click to continue" button or * after their chat messages have been sent. */ - public async sendMessage(messages: string | string[], options: SendMessageOptions): Promise; + public async sendMessage(messages: string | string[], options?: SendMessageOptions): Promise; - public async sendMessage(messages: string | string[], options: boolean | SendMessageOptions): Promise { + public async sendMessage(messages: string | string[], options?: boolean | SendMessageOptions): Promise { if(!Array.isArray(messages)) { messages = [ messages ]; } @@ -650,6 +658,8 @@ export class Player extends Actor { if(showInConsole) { messages.forEach(message => this.outgoingPackets.consoleMessage(message)); } + + return true; } /** @@ -660,20 +670,20 @@ export class Player extends Actor { public teleport(newPosition: Position, updateRegion: boolean = true): void { this.walkingQueue.clear(); const originalPosition = this.position.copy(); - this.metadata['lastPosition'] = originalPosition; + this.metadata.lastPosition = originalPosition; this.position = newPosition; - this.metadata['teleporting'] = true; + this.metadata.teleporting = true; this.updateFlags.mapRegionUpdateRequired = updateRegion; this.lastMapRegionUpdatePosition = newPosition; - const oldChunk = world.chunkManager.getChunkForWorldPosition(originalPosition); - const newChunk = world.chunkManager.getChunkForWorldPosition(newPosition); + const oldChunk = activeWorld.chunkManager.getChunkForWorldPosition(originalPosition); + const newChunk = activeWorld.chunkManager.getChunkForWorldPosition(newPosition); if(!oldChunk.equals(newChunk)) { oldChunk.removePlayer(this); newChunk.addPlayer(this); - this.metadata['updateChunk'] = { newChunk, oldChunk }; + this.metadata.updateChunk = { newChunk, oldChunk }; if(updateRegion) { this.actionPipeline.call('region_change', regionChangeActionFactory( @@ -792,10 +802,6 @@ export class Player extends Actor { this.addBonuses(item); } - //prayers and other effects that effect strength - this.effects.filter(a => a.EffectType === EffectType.Strength).forEach((effect) => { - this._bonuses.skill['strength'] += this.skills.strength.level * effect.Modifier; - }); } public sendLogMessage(message: string, isConsole: boolean): void { @@ -821,7 +827,7 @@ export class Player extends Actor { let strHelp: string = ''; if(command.args) { for(const arg of command.args) { - if(arg.defaultValue) { + if(arg.defaultValue !== undefined) { strHelp = `${strHelp} \\<${arg.name} = ${arg.defaultValue}>`; } else { strHelp = `${strHelp} \\<${arg.name}>`; @@ -846,6 +852,38 @@ export class Player extends Actor { return this.equipment.items[equipmentIndex(equipmentSlot)] || null; } + + /** + * Check if a player can equip an item + * @param item either an ItemDetails instance or the string id of the item to be checked + * @return {equipable: boolean, missingRequirements: string[]} equipable is false if for any reason the item can not + * be equipped, if it can not be equipped, a list of reasons are attached as the missingRequirements array + * + * defaults to equipable=true if the item string id does not exist + */ + public canEquipItem(item: ItemDetails | string): { equipable: boolean, missingRequirements?: string[] } { + if(typeof item === 'string') { + item = itemMap[item]; + if(!item) { + return { equipable: true } + } + } + const missingRequirements: string[] = []; + const requirements = item.equipmentData?.requirements; + if (!requirements) return { equipable: true }; + + missingRequirements.push( + ...Object.entries(requirements.skills || {}) + .filter(([skill, level]) => !this.skills.hasLevel(skill as SkillName, level)) + .map(([skill, level]) => `You need to be at least level ${level} ${skill} to equip this item.`), + ...Object.entries(requirements.quests || {}) + .filter(([quest, stage]) => this.hasQuestRequirement(quest, stage)) + .map(([quest]) => `You must progress further in the ${quest.replace(/^([a-z]+:)/gm, '').replace(/_/g, ' ')} quest to equip this item.`) + ); + + return { equipable: missingRequirements.length === 0, missingRequirements: missingRequirements }; + } + public equipItem(itemId: number, itemSlot: number, slot: EquipmentSlot | number): boolean { const itemToEquip = getItemFromContainer(itemId, itemSlot, this.inventory); @@ -862,14 +900,22 @@ export class Player extends Actor { slotIndex = equipmentIndex(slot); } - const itemToUnequip: Item = this.equipment.items[slotIndex]; - let shouldUnequipOffHand: boolean = false; - let shouldUnequipMainHand: boolean = false; - const itemDetails: ItemDetails = findItem(itemId); + const itemToUnequip = this.equipment.items[slotIndex]; + let shouldUnequipOffHand = false; + let shouldUnequipMainHand = false; + const itemDetails = findItem(itemId); if(!itemDetails || !itemDetails.equipmentData || !itemDetails.equipmentData.equipmentSlot) { - this.sendMessage(`Unable to equip item ${itemId}/${itemDetails.name}: Missing equipment data.`); - return; + this.sendMessage(`Unable to equip item ${itemId}: Missing equipment data.`); + return false; + } + + const equippable = this.canEquipItem(itemDetails); + if (!equippable.equipable) { + if(equippable.missingRequirements) { + equippable.missingRequirements.forEach(async (s) => this.sendMessage(s)); + } + return false; } if(itemDetails && itemDetails.equipmentData) { @@ -877,8 +923,10 @@ export class Player extends Actor { shouldUnequipOffHand = true; } - if(slot === 'off_hand' && this.getEquippedItem('main_hand')) { - const mainHandItemData: ItemDetails = findItem(this.getEquippedItem('main_hand').itemId); + const mainHandEquipped = this.getEquippedItem('main_hand'); + + if(slot === 'off_hand' && mainHandEquipped) { + const mainHandItemData = findItem(mainHandEquipped.itemId); if(mainHandItemData && mainHandItemData.equipmentData && mainHandItemData.equipmentData.equipmentType === 'two_handed') { shouldUnequipMainHand = true; @@ -930,12 +978,30 @@ export class Player extends Actor { if(this.interfaceState.widgetOpen('screen', widgets.equipmentStats.widgetId)) { this.outgoingPackets.sendUpdateAllWidgetItems(widgets.equipmentStats, this.equipment); - updateBonusStrings(this); + this.syncBonuses(); } this.updateFlags.appearanceUpdateRequired = true; } + public syncBonuses(): void { + [ + { id: 108, text: 'Stab', value: this.bonuses.offensive.stab }, + { id: 109, text: 'Slash', value: this.bonuses.offensive.slash }, + { id: 110, text: 'Crush', value: this.bonuses.offensive.crush }, + { id: 111, text: 'Magic', value: this.bonuses.offensive.magic }, + { id: 112, text: 'Range', value: this.bonuses.offensive.ranged }, + { id: 113, text: 'Stab', value: this.bonuses.defensive.stab }, + { id: 114, text: 'Slash', value: this.bonuses.defensive.slash }, + { id: 115, text: 'Crush', value: this.bonuses.defensive.crush }, + { id: 116, text: 'Magic', value: this.bonuses.defensive.magic }, + { id: 117, text: 'Range', value: this.bonuses.defensive.ranged }, + { id: 119, text: 'Strength', value: this.bonuses.skill.strength }, + { id: 120, text: 'Prayer', value: this.bonuses.skill.prayer }, + ].forEach(bonus => this.modifyWidget(widgets.equipmentStats.widgetId, { childId: bonus.id, + text: `${bonus.text}: ${(bonus.value || 0) > 0 ? `+${bonus.value}` : bonus.value}` })); + } + public unequipItem(slot: EquipmentSlot | number, updateRequired: boolean = true): boolean { const inventorySlot = this.inventory.getFirstOpenSlot(); if(inventorySlot === -1) { @@ -969,9 +1035,9 @@ export class Player extends Actor { /** * Transform's the player's appearance into the specified NPC. - * @param npc The NPC to copy the appearance of. + * @param npc The NPC to copy the appearance of, or null to reset. */ - public transformInto(npc: Npc | NpcDetails | string | number): void { + public transformInto(npc: Npc | NpcDetails | string | number | null): void { if(!npc) { delete this.savedMetadata.npcTransformation; this.updateFlags.appearanceUpdateRequired = true; @@ -1012,17 +1078,19 @@ export class Player extends Actor { let morphIndex: number; if (originalNpc.varbitId !== -1) { - morphIndex = getVarbitMorphIndex(originalNpc.varbitId, this.metadata['configs']); + morphIndex = getVarbitMorphIndex(originalNpc.varbitId, this.metadata.configs); } else if (originalNpc.settingId !== -1) { - morphIndex = this.metadata['configs'] && this.metadata['configs'][originalNpc.settingId] ? this.metadata['configs'][originalNpc.settingId] : 0; + morphIndex = this.metadata.configs && this.metadata.configs[originalNpc.settingId] ? this.metadata.configs[originalNpc.settingId] : 0; } else { logger.warn(`Tried to fetch a child NPC index, but but no varbitId or settingId were found in the NPC details. NPC: ${originalNpc.id}, childrenIDs: ${originalNpc.childrenIds}`); return null; } const npcDetails = findNpc(originalNpc.childrenIds[morphIndex]); - if (!npcDetails.key) { - logger.warn(`Fetched a morphed NPC, but it isn't yet registered on the server. (id-${originalNpc.id}) (morphedId-${npcDetails.gameId})`); + if (!npcDetails) { + logger.warn(`Fetched a morphed NPC, but it isn't yet registered on the server. (id-${originalNpc.id}) (morphedId-${originalNpc.childrenIds[morphIndex]})`); + + return; } return npcDetails; } @@ -1035,7 +1103,12 @@ export class Player extends Actor { if(event.type === 'CLEAR_ALL') { this.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, this.inventory); } else if(event.type === 'ADD') { - this.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, event.slot, event.item); + if (event.slot !== undefined && event.item !== undefined) { + this.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, event.slot, event.item); + } else { + logger.error(`Inventory update event was missing slot or item.`, event); + } + } this.updateCarryWeight(); } @@ -1045,12 +1118,19 @@ export class Player extends Actor { * @param chunks The chunks to update. */ private sendChunkUpdates(chunks: Chunk[]): void { + const instance = this.instance; + + if (!instance) { + logger.error(`Player ${this.username} tried to send chunk updates without an instance.`); + return; + } + chunks.forEach(chunk => { this.outgoingPackets.clearChunk(chunk); const chunkUpdateItems: ChunkUpdateItem[] = []; - const chunkModifications = this.instance + const chunkModifications = instance .getInstancedChunk(chunk.position.x, chunk.position.y, chunk.position.level) || null; const personalChunkModifications = this.personalInstance?.getInstancedChunk(chunk.position.x, chunk.position.y, chunk.position.level) || null; @@ -1096,12 +1176,13 @@ export class Player extends Actor { Object.keys(questMap).forEach(questKey => { const questData = questMap[questKey]; const playerQuest = this.quests.find(quest => quest.questId === questData.id); + let color: number; if (playerQuest?.complete) { // Quest complete, regardless of progress color = colors.green; - } else if (playerQuest?.progress > 0) { + } else if ((playerQuest?.progress || 0) > 0) { // Quest in progress, not yet complete but progress is greater than 0 color = colors.yellow; } else { @@ -1119,7 +1200,7 @@ export class Player extends Actor { private updateMusicTab(): void { if(!this.savedMetadata['currentSongIdPlaying']) { this.savedMetadata['currentSongIdPlaying'] = - findSongIdByRegionId(world.chunkManager.getRegionIdForWorldPosition( + findSongIdByRegionId(activeWorld.chunkManager.getRegionIdForWorldPosition( this.position)); } @@ -1140,7 +1221,7 @@ export class Player extends Actor { } private addBonuses(item: Item): void { - const itemData: ItemDetails = findItem(item.itemId); + const itemData = findItem(item.itemId); if(!itemData || !itemData.equipmentData) { return; @@ -1151,35 +1232,24 @@ export class Player extends Actor { const skillBonuses = itemData.equipmentData.skillBonuses; if(offensiveBonuses) { - [ 'speed', 'stab', 'slash', 'crush', 'magic', 'ranged' ].forEach(bonus => this._bonuses.offensive[bonus] += (!offensiveBonuses[bonus] ? 0 : offensiveBonuses[bonus])); + [ 'speed', 'stab', 'slash', 'crush', 'magic', 'ranged' ].forEach(bonus => + this.bonuses.offensive[bonus] += (!offensiveBonuses[bonus] ? 0 : offensiveBonuses[bonus])); } if(defensiveBonuses) { - [ 'stab', 'slash', 'crush', 'magic', 'ranged' ].forEach(bonus => this._bonuses.defensive[bonus] += (!defensiveBonuses[bonus] ? 0 : defensiveBonuses[bonus])); + [ 'stab', 'slash', 'crush', 'magic', 'ranged' ].forEach(bonus => + this.bonuses.defensive[bonus] += (!defensiveBonuses[bonus] ? 0 : defensiveBonuses[bonus])); } if(skillBonuses) { - [ 'strength', 'prayer' ].forEach(bonus => this._bonuses.skill[bonus] += (!skillBonuses[bonus] ? 0 : skillBonuses[bonus])); + [ 'strength', 'prayer' ].forEach(bonus => this.bonuses.skill[bonus] += + (!skillBonuses[bonus] ? 0 : skillBonuses[bonus])); } } - private clearBonuses(): void { - this._bonuses = { - offensive: { - speed: 0, stab: 0, slash: 0, crush: 0, magic: 0, ranged: 0 - }, - defensive: { - stab: 0, slash: 0, crush: 0, magic: 0, ranged: 0 - }, - skill: { - strength: 0, prayer: 0 - } - }; - } - private loadSaveData(): void { - const playerSave: PlayerSave = loadPlayerSave(this.username); - const firstTimePlayer: boolean = playerSave === null; + const playerSave = loadPlayerSave(this.username); + const firstTimePlayer = playerSave === null; this.firstTimePlayer = firstTimePlayer; if(!firstTimePlayer) { @@ -1249,11 +1319,11 @@ export class Player extends Actor { super.position = position; if(this.quadtreeKey !== null) { - world.playerTree.remove(this.quadtreeKey); + activeWorld.playerTree.remove(this.quadtreeKey); } this.quadtreeKey = { x: position.x, y: position.y, actor: this }; - world.playerTree.push(this.quadtreeKey); + activeWorld.playerTree.push(this.quadtreeKey); } public get position(): Position { @@ -1272,7 +1342,7 @@ export class Player extends Actor { return this._outCipher; } - public get outgoingPackets(): OutboundPackets { + public get outgoingPackets(): OutboundPacketHandler { return this._outgoingPackets; } @@ -1313,17 +1383,20 @@ export class Player extends Actor { return this._nearbyChunks; } - public get bonuses(): { offensive: OffensiveBonuses, defensive: DefensiveBonuses, skill: SkillBonuses } { - return this._bonuses; + public get instance(): WorldInstance { + return super.instance; } - public get damageType(): AttackDamageType { - if (this._bonuses.offensive.crush > 0) return AttackDamageType.Crush; - if (this._bonuses.offensive.magic > 0) return AttackDamageType.Magic; - if (this._bonuses.offensive.ranged > 0) return AttackDamageType.Range; - if (this._bonuses.offensive.slash > 0) return AttackDamageType.Slash; - if (this._bonuses.offensive.stab > 0) return AttackDamageType.Stab; - return AttackDamageType.Crush; + public set instance(value: WorldInstance | null) { + if(this.instance?.instanceId) { + this.instance.removePlayer(this); + } + + if(value) { + value.addPlayer(this); + } + + this._instance = value; } } diff --git a/src/game-engine/world/actor/player/private-messaging.ts b/src/engine/world/actor/player/private-messaging.ts similarity index 89% rename from src/game-engine/world/actor/player/private-messaging.ts rename to src/engine/world/actor/player/private-messaging.ts index 73bf01f20..eb2e7b8e8 100644 --- a/src/game-engine/world/actor/player/private-messaging.ts +++ b/src/engine/world/actor/player/private-messaging.ts @@ -1,5 +1,5 @@ import { Player } from '@engine/world/actor/player/player'; -import { world } from '@engine/game-server'; +import { activeWorld } from '@engine/world'; export enum PrivateChatMode { PUBLIC = 0, @@ -11,7 +11,7 @@ export class PrivateMessaging { public static friendAdded(player: Player, friendName: string): void { friendName = friendName.toLowerCase(); - const friend = world?.findPlayer(friendName); + const friend = activeWorld?.findPlayer(friendName); } public static friendRemoved(player: Player, friendName: string): void { @@ -19,7 +19,7 @@ export class PrivateMessaging { const playerPrivateChatMode = player.settings.privateChatMode; const playerUsername = player.username.toLowerCase(); if(playerPrivateChatMode !== PrivateChatMode.PUBLIC) { - const friend = world?.findPlayer(friendName); + const friend = activeWorld?.findPlayer(friendName); if(friend && friend.friendsList.indexOf(playerUsername) !== -1) { // Friend being removed is currently online - update their friends list if they have this player added friend.outgoingPackets.updateFriendStatus(player.username, 0); @@ -34,7 +34,7 @@ export class PrivateMessaging { public static updateFriendsList(player: Player): void { const friends = player.friendsList; if(friends && friends.length !== 0) { - const onlineFriends = world.playerList.filter(p => p && friends.indexOf(p.username.toLowerCase()) !== -1); + const onlineFriends = activeWorld.playerList.filter(p => p && friends.indexOf(p.username.toLowerCase()) !== -1); friends.forEach(friendName => { const friend = onlineFriends.find(p => p.username.toLowerCase() === friendName); @@ -64,7 +64,7 @@ export class PrivateMessaging { const playerFriendsList = player.friendsList || []; if(playerPrivateChatMode !== PrivateChatMode.OFF || updating) { - const otherPlayers = world.playerList.filter(p => p && p.friendsList.indexOf(playerName) !== -1); + const otherPlayers = activeWorld.playerList.filter(p => p && p.friendsList.indexOf(playerName) !== -1); if(otherPlayers && otherPlayers.length !== 0) { otherPlayers.forEach(otherPlayer => { let worldId = playerPrivateChatMode === PrivateChatMode.OFF ? 0 : 1; diff --git a/src/game-engine/world/actor/player/quest.ts b/src/engine/world/actor/player/quest.ts similarity index 100% rename from src/game-engine/world/actor/player/quest.ts rename to src/engine/world/actor/player/quest.ts diff --git a/src/game-engine/world/actor/player/sync/actor-sync.ts b/src/engine/world/actor/player/sync/actor-sync.ts similarity index 88% rename from src/game-engine/world/actor/player/sync/actor-sync.ts rename to src/engine/world/actor/player/sync/actor-sync.ts index 77dc61f65..8b245e53e 100644 --- a/src/game-engine/world/actor/player/sync/actor-sync.ts +++ b/src/engine/world/actor/player/sync/actor-sync.ts @@ -1,19 +1,19 @@ -import { ByteBuffer } from '@runejs/core/buffer'; +import { ByteBuffer } from '@runejs/common'; -import { world } from '@engine/game-server'; import { Packet } from '@engine/net/packet'; -import { Npc } from '@engine/world/actor/npc/npc'; +import { Npc } from '@engine/world/actor/npc'; import { Position } from '@engine/world/position'; import { QuadtreeKey } from '@engine/world'; import { Actor } from '@engine/world/actor/actor'; import { Player } from '../player'; +import { activeWorld } from '@engine/world'; /** * Handles the registration of nearby NPCs or Players for the specified player. */ export function registerNewActors(packet: Packet, player: Player, trackedActors: Actor[], nearbyActors: QuadtreeKey[], - registerActor: (actor: Actor) => void): void { + registerActor: (actor: Actor) => void): void { if(trackedActors.length >= 255) { return; } @@ -37,12 +37,12 @@ export function registerNewActors(packet: Packet, player: Player, trackedActors: continue; } - if(!world.playerOnline(nearbyActor)) { + if(!activeWorld.playerOnline(nearbyActor)) { // Other player is no longer in the game world continue; } } else if(nearbyActor instanceof Npc) { - if(!world.npcExists(nearbyActor)) { + if(!activeWorld.npcExists(nearbyActor)) { // Npc is no longer in the game world continue; } @@ -73,7 +73,7 @@ export function registerNewActors(packet: Packet, player: Player, trackedActors: * Handles synchronization of nearby NPCs or Players for the specified player. */ export function syncTrackedActors(packet: Packet, playerPosition: Position, appendUpdateMaskData: (actor: Actor) => void, - trackedActors: Actor[], nearbyActors: QuadtreeKey[]): Actor[] { + trackedActors: Actor[], nearbyActors: QuadtreeKey[]): Actor[] { packet.putBits(8, trackedActors.length); // Tracked actor count if(trackedActors.length === 0) { @@ -87,18 +87,18 @@ export function syncTrackedActors(packet: Packet, playerPosition: Position, appe let exists = true; if(trackedActor instanceof Player) { - if(!world.playerOnline(trackedActor as Player)) { + if(!activeWorld.playerOnline(trackedActor as Player)) { exists = false; } } else { - if(!world.npcExists(trackedActor as Npc)) { + if(!activeWorld.npcExists(trackedActor as Npc)) { exists = false; } } if(exists && nearbyActors.findIndex(m => m.actor.equals(trackedActor)) !== -1 && trackedActor.position.withinViewDistance(playerPosition) - && !trackedActor.metadata['teleporting']) { + && !trackedActor.metadata.teleporting) { appendMovement(trackedActor, packet); appendUpdateMaskData(trackedActor); existingTrackedActors.push(trackedActor); diff --git a/src/engine/world/actor/player/sync/index.ts b/src/engine/world/actor/player/sync/index.ts new file mode 100644 index 000000000..756f0ca17 --- /dev/null +++ b/src/engine/world/actor/player/sync/index.ts @@ -0,0 +1,3 @@ +export * from './actor-sync'; +export * from './npc-sync-task'; +export * from './player-sync-task'; diff --git a/src/game-engine/world/actor/player/sync/npc-sync-task.ts b/src/engine/world/actor/player/sync/npc-sync-task.ts similarity index 95% rename from src/game-engine/world/actor/player/sync/npc-sync-task.ts rename to src/engine/world/actor/player/sync/npc-sync-task.ts index 97596d15a..ee8268228 100644 --- a/src/game-engine/world/actor/player/sync/npc-sync-task.ts +++ b/src/engine/world/actor/player/sync/npc-sync-task.ts @@ -1,10 +1,10 @@ -import { ByteBuffer } from '@runejs/core/buffer'; +import { ByteBuffer } from '@runejs/common'; import { Packet, PacketType } from '@engine/net/packet'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { world } from '@engine/game-server'; +import { Npc } from '@engine/world/actor/npc'; import { registerNewActors, SyncTask, syncTrackedActors } from './actor-sync'; import { Player } from '../player'; +import { activeWorld } from '@engine/world'; /** @@ -26,7 +26,7 @@ export class NpcSyncTask extends SyncTask { const updateMaskData = new ByteBuffer(5000); - const nearbyNpcs = world.npcTree.colliding({ + const nearbyNpcs = activeWorld.npcTree.colliding({ x: this.player.position.x - 15, y: this.player.position.y - 15, width: 32, @@ -105,7 +105,7 @@ export class NpcSyncTask extends SyncTask { if(updateFlags.damage !== null) { const damage = updateFlags.damage; - updateMaskData.put(damage.damageType); + updateMaskData.put(damage.damageDealt); updateMaskData.put(damage.damageType.valueOf()); updateMaskData.put(damage.remainingHitpoints); updateMaskData.put(damage.maxHitpoints); diff --git a/src/game-engine/world/actor/player/sync/player-sync-task.ts b/src/engine/world/actor/player/sync/player-sync-task.ts similarity index 92% rename from src/game-engine/world/actor/player/sync/player-sync-task.ts rename to src/engine/world/actor/player/sync/player-sync-task.ts index 44eab99f7..920fceac5 100644 --- a/src/game-engine/world/actor/player/sync/player-sync-task.ts +++ b/src/engine/world/actor/player/sync/player-sync-task.ts @@ -1,13 +1,13 @@ -import { ByteBuffer } from '@runejs/core/buffer'; +import { ByteBuffer } from '@runejs/common'; import { UpdateFlags } from '@engine/world/actor/update-flags'; import { Packet, PacketType } from '@engine/net/packet'; -import { world } from '@engine/game-server'; import { stringToLong } from '@engine/util/strings'; -import { findItem, findNpc } from '@engine/config'; -import { EquipmentSlot, ItemDetails } from '@engine/config/item-config'; +import { findItem, findNpc } from '@engine/config/config-handler'; +import { EquipmentSlot, EquipmentType, ItemDetails } from '@engine/config/item-config'; import { appendMovement, registerNewActors, SyncTask, syncTrackedActors } from './actor-sync'; import { Player } from '../player'; +import { activeWorld } from '@engine/world'; /** @@ -30,10 +30,10 @@ export class PlayerSyncTask extends SyncTask { const updateMaskData = new ByteBuffer(5000); - if(updateFlags.mapRegionUpdateRequired || this.player.metadata['teleporting']) { + if(updateFlags.mapRegionUpdateRequired || this.player.metadata.teleporting) { playerUpdatePacket.putBits(1, 1); // Update Required playerUpdatePacket.putBits(2, 3); // Map Region changed (movement type - 0=nomove, 1=walk, 2=run, 3=mapchange - playerUpdatePacket.putBits(1, this.player.metadata['teleporting'] ? 1 : 0); // Whether or not the client should discard the current walking queue (1 if teleporting, 0 if not) + playerUpdatePacket.putBits(1, this.player.metadata.teleporting ? 1 : 0); // Whether or not the client should discard the current walking queue (1 if teleporting, 0 if not) playerUpdatePacket.putBits(2, this.player.position.level); // Player Height playerUpdatePacket.putBits(1, updateFlags.updateBlockRequired ? 1 : 0); // Whether or not an update flag block follows playerUpdatePacket.putBits(7, this.player.position.chunkLocalX); // Player Local Chunk X @@ -44,7 +44,7 @@ export class PlayerSyncTask extends SyncTask { this.appendUpdateMaskData(this.player, updateMaskData, false); - let nearbyPlayers = world.playerTree.colliding({ + let nearbyPlayers = activeWorld.playerTree.colliding({ x: this.player.position.x - 15, y: this.player.position.y - 15, width: 32, @@ -52,7 +52,7 @@ export class PlayerSyncTask extends SyncTask { }).filter(collision => collision?.actor && collision.actor.instance === this.player.instance); if(nearbyPlayers.length > 200) { - nearbyPlayers = world.playerTree.colliding({ + nearbyPlayers = activeWorld.playerTree.colliding({ x: this.player.position.x - 7, y: this.player.position.y - 7, width: 16, @@ -139,7 +139,7 @@ export class PlayerSyncTask extends SyncTask { if(updateFlags.damage !== null) { const damage = updateFlags.damage; - updateMaskData.put(damage.damageType); + updateMaskData.put(damage.damageDealt); updateMaskData.put(damage.damageType.valueOf()); updateMaskData.put(damage.remainingHitpoints); updateMaskData.put(damage.maxHitpoints); @@ -159,8 +159,8 @@ export class PlayerSyncTask extends SyncTask { updateMaskData.put(-1, 'SHORT', 'LITTLE_ENDIAN'); updateMaskData.put(0, 'BYTE'); } else { - const delay = updateFlags.animation.delay || 0; - updateMaskData.put(updateFlags.animation.id, 'SHORT', 'LITTLE_ENDIAN'); + const delay = animation.delay || 0; + updateMaskData.put(animation.id, 'SHORT', 'LITTLE_ENDIAN'); updateMaskData.put(delay, 'BYTE'); } } @@ -187,7 +187,12 @@ export class PlayerSyncTask extends SyncTask { if(updateFlags.chatMessages.length !== 0) { const message = updateFlags.chatMessages[0]; - updateMaskData.put(((message.color & 0xFF) << 8) + (message.effects & 0xFF), 'SHORT'); + + if (!message.data) { + throw new Error('Chat message data is undefined'); + } + + updateMaskData.put(((message.color || 0 & 0xFF) << 8) + (message.effects || 0 & 0xFF), 'SHORT'); updateMaskData.put(player.rights.valueOf(), 'BYTE'); updateMaskData.put(message.data.length, 'BYTE'); for(let i = 0; i < message.data.length; i++) { @@ -217,7 +222,7 @@ export class PlayerSyncTask extends SyncTask { } const torsoItem = player.getEquippedItem('torso'); - let torsoItemData: ItemDetails = null; + let torsoItemData: ItemDetails | null = null; if(torsoItem) { torsoItemData = findItem(torsoItem.itemId); appearanceData.put(0x200 + torsoItem.itemId, 'SHORT'); @@ -242,7 +247,7 @@ export class PlayerSyncTask extends SyncTask { this.appendBasicAppearanceItem(appearanceData, player, player.appearance.legs, 'legs'); const headItem = player.getEquippedItem('head'); - let helmetType = null; + let helmetType: EquipmentType | null = null; let fullHelmet = false; if(headItem) { diff --git a/src/engine/world/actor/prayer.ts b/src/engine/world/actor/prayer.ts new file mode 100644 index 000000000..18c042362 --- /dev/null +++ b/src/engine/world/actor/prayer.ts @@ -0,0 +1,5 @@ +export class Prayer { + AnimationId: number; + SoundId: number; + ButtonId: number; +} diff --git a/src/game-engine/world/actor/skills.ts b/src/engine/world/actor/skills.ts similarity index 97% rename from src/game-engine/world/actor/skills.ts rename to src/engine/world/actor/skills.ts index d5323342a..d38df6e13 100644 --- a/src/game-engine/world/actor/skills.ts +++ b/src/engine/world/actor/skills.ts @@ -1,9 +1,8 @@ -import { Actor } from '@engine/world/actor/actor'; -import { Player } from '@engine/world/actor/player/player'; import { startsWithVowel } from '@engine/util/strings'; -import { serverConfig } from '@engine/game-server'; -import { gfxIds } from '@engine/world/config/gfx-ids'; -import equipmentStatsPlugin from '../../../plugins/items/equipment/equipment-stats.plugin'; +import { serverConfig } from '@server/game/game-server'; +import { gfxIds } from '@engine/world/config'; +import { Actor } from './actor'; +import { Player } from './player'; export enum Skill { ATTACK, @@ -61,7 +60,7 @@ export const skillDetails: SkillDetail[] = [ { name: 'Slayer', advancementWidgetId: 173 }, { name: 'Farming', advancementWidgetId: 162 }, { name: 'Runecrafting', advancementWidgetId: 172 }, - null, + null as unknown as SkillDetail, // (Jameskmonger) this is a placeholder { name: 'Construction' } ]; diff --git a/src/game-engine/world/actor/update-flags.ts b/src/engine/world/actor/update-flags.ts similarity index 79% rename from src/game-engine/world/actor/update-flags.ts rename to src/engine/world/actor/update-flags.ts index 715bff6e7..4344c7308 100644 --- a/src/game-engine/world/actor/update-flags.ts +++ b/src/engine/world/actor/update-flags.ts @@ -1,5 +1,5 @@ import { Position } from '../position'; -import { Actor } from '@engine/world/actor/actor'; +import { Actor } from './actor'; /** * A specific chat message. @@ -52,11 +52,11 @@ export class UpdateFlags { private _mapRegionUpdateRequired: boolean; private _appearanceUpdateRequired: boolean; private _chatMessages: ChatMessage[]; - private _facePosition: Position; - private _faceActor: Actor; - private _graphics: Graphic; - private _animation: Animation; - private _damage: Damage; + private _facePosition: Position | null; + private _faceActor: Actor | null; + private _graphics: Graphic | null; + private _animation: Animation | null; + private _damage: Damage | null; public constructor() { this._chatMessages = []; @@ -67,9 +67,9 @@ export class UpdateFlags { this._mapRegionUpdateRequired = false; this._appearanceUpdateRequired = false; this._facePosition = null; - this._faceActor = undefined; + this._faceActor = null; this._graphics = null; - this._animation = undefined; + this._animation = null; this._damage = null; if(this._chatMessages.length !== 0) { @@ -122,43 +122,43 @@ export class UpdateFlags { this._chatMessages = value; } - public get facePosition(): Position { + public get facePosition(): Position | null { return this._facePosition; } - public set facePosition(value: Position) { + public set facePosition(value: Position | null) { this._facePosition = value; } - public get faceActor(): Actor { + public get faceActor(): Actor | null { return this._faceActor; } - public set faceActor(value: Actor) { + public set faceActor(value: Actor | null) { this._faceActor = value; } - public get graphics(): Graphic { + public get graphics(): Graphic | null { return this._graphics; } - public set graphics(value: Graphic) { + public set graphics(value: Graphic | null) { this._graphics = value; } - public get animation(): Animation { + public get animation(): Animation | null { return this._animation; } - public set animation(value: Animation) { + public set animation(value: Animation | null) { this._animation = value; } - public get damage(): Damage { + public get damage(): Damage | null { return this._damage; } - public set damage(value: Damage) { + public set damage(value: Damage | null) { this._damage = value; } } diff --git a/src/game-engine/world/actor/walking-queue.ts b/src/engine/world/actor/walking-queue.ts similarity index 87% rename from src/game-engine/world/actor/walking-queue.ts rename to src/engine/world/actor/walking-queue.ts index db7e43c15..0e9902a31 100644 --- a/src/game-engine/world/actor/walking-queue.ts +++ b/src/engine/world/actor/walking-queue.ts @@ -1,10 +1,11 @@ import { Actor } from './actor'; import { Position } from '../position'; import { Player } from './player/player'; -import { world } from '@engine/game-server'; -import { Npc } from './npc/npc'; -import { regionChangeActionFactory } from '@engine/world/action/region-change.action'; +import { Npc } from './npc'; +import { regionChangeActionFactory } from '@engine/action'; import { Subject } from 'rxjs'; +import { activeWorld } from '@engine/world'; +import { logger } from '@runejs/common'; /** @@ -67,7 +68,10 @@ export class WalkingQueue { if(this.actor.pathfinding.canMoveTo(lastPosition, newPosition)) { lastPosition = newPosition; - newPosition.metadata = positionMetadata; + newPosition.metadata = { + ...newPosition.metadata, + ...positionMetadata + }; this.queue.push(newPosition); this.movementQueued.next(newPosition); } else { @@ -80,7 +84,10 @@ export class WalkingQueue { const newPosition = new Position(x, y, this.actor.position.level); if(this.actor.pathfinding.canMoveTo(lastPosition, newPosition)) { - newPosition.metadata = positionMetadata; + newPosition.metadata = { + ...newPosition.metadata, + ...positionMetadata + }; this.queue.push(newPosition); this.movementQueued.next(newPosition); } else { @@ -144,14 +151,18 @@ export class WalkingQueue { const walkPosition = this.queue.shift(); - if(this.actor.metadata['faceActorClearedByWalking'] === undefined || this.actor.metadata['faceActorClearedByWalking']) { + if (!walkPosition) { + return; + } + + if(this.actor.metadata.faceActorClearedByWalking === undefined || this.actor.metadata.faceActorClearedByWalking) { this.actor.clearFaceActor(); } const originalPosition = this.actor.position; if(this.actor.pathfinding.canMoveTo(originalPosition, walkPosition)) { - const oldChunk = world.chunkManager.getChunkForWorldPosition(originalPosition); + const oldChunk = activeWorld.chunkManager.getChunkForWorldPosition(originalPosition); const lastMapRegionUpdatePosition = this.actor.lastMapRegionUpdatePosition; const walkDiffX = walkPosition.x - originalPosition.x; @@ -173,6 +184,10 @@ export class WalkingQueue { if(this.actor.settings.runEnabled && this.queue.length !== 0) { const runPosition = this.queue.shift(); + if (!runPosition) { + return; + } + if(this.actor.pathfinding.canMoveTo(walkPosition, runPosition)) { const runDiffX = runPosition.x - walkPosition.x; const runDiffY = runPosition.y - walkPosition.y; @@ -198,7 +213,7 @@ export class WalkingQueue { this.actor.faceDirection = walkDir; } - const newChunk = world.chunkManager.getChunkForWorldPosition(this.actor.position); + const newChunk = activeWorld.chunkManager.getChunkForWorldPosition(this.actor.position); this.movementEvent.next(this.actor.position); @@ -213,7 +228,7 @@ export class WalkingQueue { if(!oldChunk.equals(newChunk)) { if(this.actor instanceof Player) { - this.actor.metadata['updateChunk'] = { newChunk, oldChunk }; + this.actor.metadata.updateChunk = { newChunk, oldChunk }; this.actor.actionPipeline.call('region_change', regionChangeActionFactory( this.actor, originalPosition, this.actor.position)); diff --git a/src/game-engine/world/config/animation-ids.ts b/src/engine/world/config/animation-ids.ts similarity index 100% rename from src/game-engine/world/config/animation-ids.ts rename to src/engine/world/config/animation-ids.ts diff --git a/src/game-engine/world/config/examine-data.ts b/src/engine/world/config/examine-data.ts similarity index 88% rename from src/game-engine/world/config/examine-data.ts rename to src/engine/world/config/examine-data.ts index a006964e3..61b8344f5 100644 --- a/src/game-engine/world/config/examine-data.ts +++ b/src/engine/world/config/examine-data.ts @@ -1,5 +1,5 @@ import { readFileSync } from 'fs'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; import { JSON_SCHEMA, safeLoad } from 'js-yaml'; interface Examine { @@ -19,17 +19,17 @@ export class ExamineCache { this.objects = new Map(); } - public getItem (id: number): string { + public getItem (id: number): string | null { const examine = this.items.get(id); return examine ? examine.examine : null; } - public getNpc (id: number): string { + public getNpc (id: number): string | null { const examine = this.npcs.get(id); return examine ? examine.examine : null; } - public getObject (id: number): string { + public getObject (id: number): string | null { const examine = this.objects.get(id); return examine ? examine.examine : null; } diff --git a/src/game-engine/world/config/gfx-ids.ts b/src/engine/world/config/gfx-ids.ts similarity index 100% rename from src/game-engine/world/config/gfx-ids.ts rename to src/engine/world/config/gfx-ids.ts diff --git a/src/game-engine/world/config/harvest-tool.ts b/src/engine/world/config/harvest-tool.ts similarity index 100% rename from src/game-engine/world/config/harvest-tool.ts rename to src/engine/world/config/harvest-tool.ts diff --git a/src/game-engine/world/config/harvestable-object.ts b/src/engine/world/config/harvestable-object.ts similarity index 86% rename from src/game-engine/world/config/harvestable-object.ts rename to src/engine/world/config/harvestable-object.ts index ae2bb83c5..f936432d2 100644 --- a/src/game-engine/world/config/harvestable-object.ts +++ b/src/engine/world/config/harvestable-object.ts @@ -78,12 +78,20 @@ const TEAK_OBJECTS: Map = new Map([ ...objectIds.tree.teak.map((tree) => [tree.default, tree.stump]), ] as [number, number][]); +const DRAMEN_OBJECTS: Map = new Map([ + ...objectIds.tree.dramen.map((tree) => [tree.default, tree.stump]), +] as [number, number][]); + const MAPLE_OBJECTS: Map = new Map([ ...objectIds.tree.maple.map((tree) => [tree.default, tree.stump]), ] as [number, number][]); +const HOLLOW_OBJECTS: Map = new Map([ + ...objectIds.tree.hollow.map((tree) => [tree.default, tree.stump]), +] as [number, number][]); + const MAHOGANY_OBJECTS: Map = new Map([ ...objectIds.tree.mahogany.map((tree) => [tree.default, tree.stump]), ] as [number, number][]); @@ -245,8 +253,8 @@ const Trees: IHarvestable[] = [ itemId: itemIds.logs.normal, level: 1, experience: 25, - respawnLow: 10, - respawnHigh: 20, + respawnLow: 59, + respawnHigh: 98, baseChance: 70, break: 100 }, @@ -255,8 +263,8 @@ const Trees: IHarvestable[] = [ itemId: itemIds.logs.achey, level: 1, experience: 25, - respawnLow: 10, - respawnHigh: 20, + respawnLow: 59, + respawnHigh: 98, baseChance: 70, break: 100 }, @@ -265,8 +273,8 @@ const Trees: IHarvestable[] = [ itemId: itemIds.logs.oak, level: 15, experience: 37.5, - respawnLow: 20, - respawnHigh: 30, + respawnLow: 14, + respawnHigh: 14, baseChance: 50, break: 100 / 8 }, @@ -275,8 +283,8 @@ const Trees: IHarvestable[] = [ itemId: itemIds.logs.willow, level: 30, experience: 67.5, - respawnLow: 40, - respawnHigh: 50, + respawnLow: 14, + respawnHigh: 14, baseChance: 30, break: 100 / 8 }, @@ -285,18 +293,39 @@ const Trees: IHarvestable[] = [ itemId: itemIds.logs.teak, level: 35, experience: 85, - respawnLow: 50, - respawnHigh: 60, + respawnLow: 15, + respawnHigh: 15, baseChance: 0, break: 100 / 8 }, + + { + objects: DRAMEN_OBJECTS, + itemId: itemIds.logs.dramenbranch, + level: 36, + experience: 0, + respawnLow: 0, + respawnHigh: 0, + baseChance: 100, + break: 0 + }, { objects: MAPLE_OBJECTS, itemId: itemIds.logs.maple, level: 45, experience: 100, - respawnLow: 100, - respawnHigh: 120, + respawnLow: 59, + respawnHigh: 59, + baseChance: 0, + break: 100 / 8 + }, + { + objects: HOLLOW_OBJECTS, + itemId: itemIds.logs.bark, + level: 45, + experience: 82.5, + respawnLow: 43, + respawnHigh: 44, baseChance: 0, break: 100 / 8 }, @@ -305,8 +334,8 @@ const Trees: IHarvestable[] = [ itemId: itemIds.logs.mahogany, level: 50, experience: 125, - respawnLow: 200, - respawnHigh: 220, + respawnLow: 14, + respawnHigh: 14, baseChance: -5, break: 100 / 8 }, @@ -315,8 +344,8 @@ const Trees: IHarvestable[] = [ itemId: itemIds.logs.yew, level: 60, experience: 175, - respawnLow: 300, - respawnHigh: 320, + respawnLow: 99, + respawnHigh: 99, baseChance: -15, break: 100 / 8 }, @@ -325,8 +354,8 @@ const Trees: IHarvestable[] = [ itemId: itemIds.logs.magic, level: 75, experience: 250, - respawnLow: 800, - respawnHigh: 820, + respawnLow: 199, + respawnHigh: 199, baseChance: -25, break: 100 / 8 }, @@ -337,11 +366,11 @@ export function getOre(ore: Ore): IHarvestable { } export function getOreFromRock(id: number): IHarvestable { - return Ores.find(ore => ore.objects.has(id)); + return Ores.find(ore => ore.objects.has(id)) as IHarvestable; } export function getTreeFromHealthy(id: number): IHarvestable { - return Trees.find(tree => tree.objects.has(id)); + return Trees.find(tree => tree.objects.has(id)) as IHarvestable; } export function getOreFromDepletedRock(id: number): IHarvestable { @@ -352,7 +381,7 @@ export function getOreFromDepletedRock(id: number): IHarvestable { } } return false; - }); + }) as IHarvestable; } export function getAllOreIds(): number[] { diff --git a/src/engine/world/config/index.ts b/src/engine/world/config/index.ts new file mode 100644 index 000000000..ca52a4a6f --- /dev/null +++ b/src/engine/world/config/index.ts @@ -0,0 +1,12 @@ +export * from './animation-ids'; +export * from './examine-data'; +export * from './gfx-ids'; +export * from './harvest-tool'; +export * from './harvestable-object'; +export * from './item-ids'; +export * from './object-ids'; +export * from './scenery-spawns'; +export * from './songs'; +export * from './sound-ids'; +export * from './travel-locations'; +export * from './widget'; diff --git a/src/game-engine/world/config/item-ids.ts b/src/engine/world/config/item-ids.ts similarity index 99% rename from src/game-engine/world/config/item-ids.ts rename to src/engine/world/config/item-ids.ts index 2159a52da..8eb5b78d9 100644 --- a/src/game-engine/world/config/item-ids.ts +++ b/src/engine/world/config/item-ids.ts @@ -398,7 +398,9 @@ export const itemIds = { oak: 1521, willow: 1519, teak: 6333, + dramenbranch:771, maple: 1517, + bark: 3239, mahogany: 6332, yew: 1515, magic: 1513 diff --git a/src/game-engine/world/config/object-ids.ts b/src/engine/world/config/object-ids.ts similarity index 64% rename from src/game-engine/world/config/object-ids.ts rename to src/engine/world/config/object-ids.ts index 6d26d6724..f6ce43364 100644 --- a/src/game-engine/world/config/object-ids.ts +++ b/src/engine/world/config/object-ids.ts @@ -26,51 +26,87 @@ export const objectIds = { tree: { normal: [ { default: 1276, stump: 1342 }, - { default: 1278, stump: 1342 } + { default: 1277, stump: 1343 }, + { default: 1278, stump: 1342 }, + { default: 1279, stump: 1345 }, + { default: 1280, stump: 1343 }, + { default: 1315, stump: 1342 }, + { default: 1316, stump: 1355 }, + { default: 1318, stump: 1355 }, + { default: 1319, stump: 1355 }, + { default: 1330, stump: 1357 }, + { default: 1331, stump: 1357 }, + { default: 1332, stump: 1357 }, + { default: 3033, stump: 1345 }, + { default: 3034, stump: 1345 }, + { default: 3879, stump: 3880 }, + { default: 3881, stump: 3880 }, + { default: 3882, stump: 3880 }, + // { default: 3883, stump: 3884 }, // sigex: no matching stump + { default: 14308, stump: 1342 }, // Sigex questionable object, high value + { default: 14309, stump: 1342 }, // Sigex questionable object, high value ], dead: [ + // Sigex: OSRS has an extra root on the stump too { default: 1282, stump: 1347 }, { default: 1283, stump: 1347 }, + { default: 1284, stump: 1348 }, + { default: 1285, stump: 1349 }, { default: 1286, stump: 1351 }, { default: 1289, stump: 1353 }, - { default: 1365, stump: 1352 } + { default: 1290, stump: 1354 }, + { default: 1291, stump: 1351 }, + { default: 1365, stump: 1352 }, + { default: 1383, stump: 1358 }, + { default: 1384, stump: 1359 }, + { default: 3035, stump: 1347 }, + // { default: 3036, stump: 1351 },// Sigex: no suitable stump offset looks wrong + { default: 5902, stump: 1347 }, + { default: 5903, stump: 1351 }, + { default: 5904, stump: 1351 }, ], archey: [ { default: 2023, stump: 3371 } ], oak: [ - { default: 1281, stump: 1342 }, - { default: 3037, stump: 1342 } + { default: 1281, stump: 1356 }, + // { default: 3037, stump: 1342 }, // Sigex: dark Oak tutorial island no stump + { default: 8467, stump: 0 } // Farming ], willow: [ - { default: 5551, stump: 1324 }, - { default: 1308, stump: 1324 }, - { default: 5552, stump: 1324 }, - { default: 5553, stump: 1324 }, - { default: 8481, stump: 1324 }, - { default: 8482, stump: 1324 }, - { default: 8483, stump: 1324 }, - { default: 8484, stump: 1324 }, - { default: 8485, stump: 1324 }, - { default: 8486, stump: 1324 }, - { default: 8487, stump: 1324 }, - { default: 8488, stump: 1324 }, + { default: 1308, stump: 7399 }, + { default: 5551, stump: 5554 }, + { default: 5552, stump: 5554 }, // Sigex: offset is wrong + { default: 5553, stump: 5554 }, // Sigex: offset is wrong + { default: 8487, stump: 1324 }, // Farming + // { default: 8488, stump: 1324 }, // Farming ], teak: [ - { default: 9036, stump: 1342 }, + { default: 9036, stump: 9037 }, + { default: 15062, stump: 9037 }, // Sigex: questionable object, high value + ], + dramen: [ + { default: 1292, stump: -1 }, ], maple: [ - { default: 1307, stump: 1342 }, - { default: 4674, stump: 1342 }, + { default: 1307, stump: 7400 }, + { default: 4674, stump: 7400 }, + // { default: 8444, stump: 0 }, // Farming + ], + hollow: [ + { default: 2289, stump: 2310 }, + { default: 4060, stump: 4061 }, ], mahogany: [ - { default: 9034, stump: 1342 }, + { default: 9034, stump: 9035 }, ], yew: [ - { default: 1309, stump: 1342 }, + { default: 1309, stump: 7402 }, + // { default: 8513, stump: 0 }, // Farming ], magic: [ - { default: 1292, stump: 1324 }, + { default: 1306, stump: 7401 }, + // { default: 8409, stump: 0 }, // Farming ], }, default: { diff --git a/src/game-engine/world/config/scenery-spawns.ts b/src/engine/world/config/scenery-spawns.ts similarity index 92% rename from src/game-engine/world/config/scenery-spawns.ts rename to src/engine/world/config/scenery-spawns.ts index 3a5fb22c0..82ba8d66d 100644 --- a/src/game-engine/world/config/scenery-spawns.ts +++ b/src/engine/world/config/scenery-spawns.ts @@ -1,4 +1,4 @@ -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; import { JSON_SCHEMA, safeLoad } from 'js-yaml'; import { readFileSync } from 'fs'; import { LandscapeObject } from '@runejs/filestore'; @@ -19,6 +19,6 @@ export function parseScenerySpawns(): LandscapeObject[] { return scenerySpawns; } catch(error) { logger.error('Error parsing scenery spawns: ' + error); - return null; + return []; } } diff --git a/src/game-engine/world/config/songs.ts b/src/engine/world/config/songs.ts similarity index 100% rename from src/game-engine/world/config/songs.ts rename to src/engine/world/config/songs.ts diff --git a/src/game-engine/world/config/sound-ids.ts b/src/engine/world/config/sound-ids.ts similarity index 100% rename from src/game-engine/world/config/sound-ids.ts rename to src/engine/world/config/sound-ids.ts diff --git a/src/game-engine/world/config/travel-locations.ts b/src/engine/world/config/travel-locations.ts similarity index 92% rename from src/game-engine/world/config/travel-locations.ts rename to src/engine/world/config/travel-locations.ts index aa21d3ebf..d1f8d427a 100644 --- a/src/game-engine/world/config/travel-locations.ts +++ b/src/engine/world/config/travel-locations.ts @@ -27,14 +27,14 @@ const readLocations = (): TravelLocation[] => { }) as TravelLocation[]; }; -export default class TravelLocations { +export class TravelLocations { public readonly locations: TravelLocation[]; public constructor () { this.locations = readLocations(); } - public find (search: string): TravelLocation { + public find (search: string): TravelLocation | null { search = search.toLowerCase().trim(); for (const location of this.locations) { if (location.key.indexOf(search) >= 0) { diff --git a/src/game-engine/world/config/widget.ts b/src/engine/world/config/widget.ts similarity index 100% rename from src/game-engine/world/config/widget.ts rename to src/engine/world/config/widget.ts diff --git a/src/game-engine/world/direction.ts b/src/engine/world/direction.ts similarity index 99% rename from src/game-engine/world/direction.ts rename to src/engine/world/direction.ts index c62f4d77c..7707f9dd3 100644 --- a/src/game-engine/world/direction.ts +++ b/src/engine/world/direction.ts @@ -61,7 +61,7 @@ export const directionData: { [key: string]: DirectionData } = { }; export const WNES: Direction[] = ['WEST', 'NORTH', 'EAST', 'SOUTH']; -export const directionFromIndex = (index: number): DirectionData => { +export const directionFromIndex = (index: number): DirectionData | null => { const keys = Object.keys(directionData); for (const key of keys) { if (directionData[key].index === index) { diff --git a/src/engine/world/index.ts b/src/engine/world/index.ts new file mode 100644 index 000000000..dbd32f1dc --- /dev/null +++ b/src/engine/world/index.ts @@ -0,0 +1,25 @@ +import { World } from '@engine/world'; + +export * from './items'; +export * from './map'; + +export * from './direction'; +export * from './instances'; +export * from './position'; +export * from './task'; +export * from './world'; + +/** + * The singleton instance of this game world. + */ +export let activeWorld: World; + + +/** + * Creates a new instance of the game world and assigns it to the singleton world variable. + */ +export const activateGameWorld = async (): Promise => { + activeWorld = new World(); + await activeWorld.startup(); + return activeWorld; +}; diff --git a/src/game-engine/world/instances.ts b/src/engine/world/instances.ts similarity index 85% rename from src/game-engine/world/instances.ts rename to src/engine/world/instances.ts index 5d1f833a7..74584afbb 100644 --- a/src/game-engine/world/instances.ts +++ b/src/engine/world/instances.ts @@ -1,13 +1,13 @@ import { Position } from '@engine/world/position'; -import { world } from '@engine/game-server'; import { WorldItem } from '@engine/world/items/world-item'; import { Item } from '@engine/world/items/item'; import { Player } from '@engine/world/actor/player/player'; -import { World } from '@engine/world/index'; +import { World } from '@engine/world'; import { schedule } from '@engine/world/task'; import { CollisionMap } from '@engine/world/map/collision-map'; import { LandscapeObject } from '@runejs/filestore'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; +import { activeWorld } from '@engine/world/index'; /** @@ -94,10 +94,9 @@ export class WorldInstance { /** * Creates a new game world instance. - * @param instanceId [optional] The instanceId to apply to this new world instance. - * If not provided, the instance will be considered a public global world instance. + * @param instanceId The instanceId to apply to this new world instance. */ - public constructor(public readonly instanceId: string = null) { + public constructor(public readonly instanceId: string) { } /** @@ -132,7 +131,7 @@ export class WorldInstance { owner.outgoingPackets.setWorldItem(worldItem, worldItem.position); } catch(error) { logger.error(`Error spawning world item ${worldItem?.itemId} at ${worldItem?.position?.key}`, error); - return null; + throw error; } } @@ -174,12 +173,12 @@ export class WorldInstance { public despawnWorldItem(worldItem: WorldItem): void { const chunkMap = this.getInstancedChunk(worldItem.position); - if(!chunkMap.mods.has(worldItem.position.key)) { + const chunkMod = chunkMap.mods.get(worldItem.position.key); + if(!chunkMod) { // Object no longer exists return; } - const chunkMod = chunkMap.mods.get(worldItem.position.key); if(chunkMod.worldItems && chunkMod.worldItems.length !== 0) { const idx = chunkMod.worldItems.findIndex(i => i.itemId === worldItem.itemId && i.amount === worldItem.amount); if(idx !== -1) { @@ -204,6 +203,11 @@ export class WorldInstance { * @param worldItem The item to re-spawn. */ public async respawnItem(worldItem: WorldItem): Promise { + if (worldItem.respawns === undefined) { + logger.warn(`Attempting to respawn item ${worldItem.itemId} at ${worldItem.position.key} that does not have a respawn time.`); + return; + } + await schedule(worldItem.respawns); this.spawnWorldItem({ @@ -224,7 +228,7 @@ export class WorldInstance { * before being shown to other players in the instance. */ public worldItemAdded(worldItem: WorldItem, excludePlayer?: Player): void { - const nearbyPlayers = world.findNearbyPlayers(worldItem.position, 16, this.instanceId) || []; + const nearbyPlayers = activeWorld.findNearbyPlayers(worldItem.position, 16, this.instanceId) || []; nearbyPlayers.forEach(player => { if(excludePlayer && excludePlayer.equals(player)) { @@ -240,7 +244,7 @@ export class WorldInstance { * @param worldItem The world item that was removed. */ public worldItemRemoved(worldItem: WorldItem): void { - const nearbyPlayers = world.findNearbyPlayers(worldItem.position, 16, this.instanceId) || []; + const nearbyPlayers = activeWorld.findNearbyPlayers(worldItem.position, 16, this.instanceId) || []; nearbyPlayers.forEach(player => player.outgoingPackets.removeWorldItem(worldItem, worldItem.position)); @@ -341,7 +345,7 @@ export class WorldInstance { instancedChunk.collisionMap.markGameObject(object, true); - const nearbyPlayers = world.findNearbyPlayers(position, 16, this.instanceId) || []; + const nearbyPlayers = activeWorld.findNearbyPlayers(position, 16, this.instanceId) || []; nearbyPlayers.forEach(player => player.outgoingPackets.setLocationObject(object, position)); } @@ -353,12 +357,12 @@ export class WorldInstance { const position = new Position(object.x, object.y, object.level); const instancedChunk = this.getInstancedChunk(position); - if(!instancedChunk.mods.has(position.key)) { + const tileModifications = instancedChunk.mods.get(position.key); + if(!tileModifications) { // Object no longer exists return; } - const tileModifications = instancedChunk.mods.get(position.key); if(tileModifications.spawnedObjects && tileModifications.spawnedObjects.length !== 0) { const idx = tileModifications.spawnedObjects.findIndex(o => o.objectId === object.objectId && o.type === object.type && o.orientation === object.orientation); @@ -373,7 +377,7 @@ export class WorldInstance { instancedChunk.collisionMap.markGameObject(object, false); - const nearbyPlayers = world.findNearbyPlayers(position, 16, this.instanceId) || []; + const nearbyPlayers = activeWorld.findNearbyPlayers(position, 16, this.instanceId) || []; nearbyPlayers.forEach(player => player.outgoingPackets.removeLocationObject(object, position)); } @@ -391,7 +395,7 @@ export class WorldInstance { instancedChunk.collisionMap.markGameObject(object, false); - const nearbyPlayers = world.findNearbyPlayers(position, 16, this.instanceId) || []; + const nearbyPlayers = activeWorld.findNearbyPlayers(position, 16, this.instanceId) || []; nearbyPlayers.forEach(player => player.outgoingPackets.removeLocationObject(object, position)); } @@ -403,12 +407,13 @@ export class WorldInstance { const position = new Position(object.x, object.y, object.level); const instancedChunk = this.getInstancedChunk(position); - if(!instancedChunk.mods.has(position.key)) { + const tileModifications = instancedChunk.mods.get(position.key); + + if(!tileModifications) { // Object no longer exists return; } - const tileModifications = instancedChunk.mods.get(position.key); if(tileModifications.hiddenObjects && tileModifications.hiddenObjects.length !== 0) { const idx = tileModifications.hiddenObjects.findIndex(o => o.objectId === object.objectId && o.type === object.type && o.orientation === object.orientation); @@ -423,7 +428,7 @@ export class WorldInstance { instancedChunk.collisionMap.markGameObject(object, true); - const nearbyPlayers = world.findNearbyPlayers(position, 16, this.instanceId) || []; + const nearbyPlayers = activeWorld.findNearbyPlayers(position, 16, this.instanceId) || []; nearbyPlayers.forEach(player => player.outgoingPackets.setLocationObject(object, position)); } @@ -443,21 +448,33 @@ export class WorldInstance { public getInstancedChunk(x: number, y: number, level: number): InstancedChunk; public getInstancedChunk(worldPositionOrX: Position | number, y?: number, level?: number): InstancedChunk { - let chunkPosition: Position; + let chunkPosition: Position | null = null; if(typeof worldPositionOrX === 'number') { - const chunk = world.chunkManager.getChunk({ x: worldPositionOrX, y, level }) || null; + const chunk = activeWorld.chunkManager.getChunk({ + x: worldPositionOrX, + + // using ! here because we know that if the first parameter is a number, the other two will be too + /* eslint-disable @typescript-eslint/no-non-null-assertion */ + y: y!, + level: level! + /* eslint-enable @typescript-eslint/no-non-null-assertion */ + }); + if(chunk) { chunkPosition = chunk.position; } } else { - chunkPosition = world.chunkManager.getChunkForWorldPosition(worldPositionOrX)?.position || null; + chunkPosition = activeWorld.chunkManager.getChunkForWorldPosition(worldPositionOrX)?.position || null; } if(!chunkPosition) { // Chunk not found - fail gracefully + logger.error('Failed to find chunk for world position', worldPositionOrX, y, level); + logger.error('Something has likely gone horribly wrong!'); + return { - collisionMap: new CollisionMap(chunkPosition.x, chunkPosition.y, chunkPosition.level, { instance: this }), + collisionMap: new CollisionMap(0, 0, 0, { instance: this }), mods: new Map() }; } @@ -469,7 +486,9 @@ export class WorldInstance { }); } - return this.chunkModifications.get(chunkPosition.key); + // using ! here because we know the chunk exists, as we've just created it if it didn't + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return this.chunkModifications.get(chunkPosition.key)!; } /** @@ -479,10 +498,15 @@ export class WorldInstance { public getTileModifications(worldPosition: Position): { chunk: InstancedChunk, mods: TileModifications } { const instancedChunk = this.getInstancedChunk(worldPosition); if(instancedChunk.mods.has(worldPosition.key)) { - return { chunk: instancedChunk, mods: instancedChunk.mods.get(worldPosition.key) }; - } else { - return { chunk: instancedChunk, mods: new TileModifications() }; + return { + chunk: instancedChunk, + // using ! here because we know it exists + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + mods: instancedChunk.mods.get(worldPosition.key)! + }; } + + return { chunk: instancedChunk, mods: new TileModifications() }; } /** @@ -504,8 +528,8 @@ export class WorldInstance { if(this.instanceId !== null && this.players.size === 0) { this.chunkModifications.clear(); - const instancedNpcs = world.findNpcsByInstance(this.instanceId); - instancedNpcs?.forEach(npc => world.deregisterNpc(npc)); + const instancedNpcs = activeWorld.findNpcsByInstance(this.instanceId); + instancedNpcs?.forEach(npc => activeWorld.deregisterNpc(npc)); } } @@ -517,11 +541,15 @@ export class WorldInstance { */ private clearTileIfEmpty(worldPosition: Position): void { const instancedChunk = this.getInstancedChunk(worldPosition); - if(instancedChunk.mods.has(worldPosition.key)) { - const mods = instancedChunk.mods.get(worldPosition.key); - if(mods.empty) { - instancedChunk.mods.delete(worldPosition.key); - } + + const mods = instancedChunk.mods.get(worldPosition.key); + + if (!mods) { + return; + } + + if(mods.empty) { + instancedChunk.mods.delete(worldPosition.key); } } diff --git a/src/engine/world/items/index.ts b/src/engine/world/items/index.ts new file mode 100644 index 000000000..09889e421 --- /dev/null +++ b/src/engine/world/items/index.ts @@ -0,0 +1,3 @@ +export * from './item'; +export * from './item-container'; +export * from './world-item'; diff --git a/src/game-engine/world/items/item-container.ts b/src/engine/world/items/item-container.ts similarity index 77% rename from src/game-engine/world/items/item-container.ts rename to src/engine/world/items/item-container.ts index 8596c717a..ed291a045 100644 --- a/src/game-engine/world/items/item-container.ts +++ b/src/engine/world/items/item-container.ts @@ -1,18 +1,19 @@ import { Item } from './item'; import { Subject } from 'rxjs'; -import { filestore } from '@engine/game-server'; +import { filestore } from '@server/game/game-server'; import { hasValueNotNull } from '@engine/util/data'; -import { findItem } from '@engine/config'; -import { logger } from '@runejs/core'; +import { findItem } from '@engine/config/config-handler'; +import { logger } from '@runejs/common'; +import { fromNote } from '@engine/world/items/item'; export interface ContainerUpdateEvent { slot?: number; - item?: Item; + item?: Item | null; type: 'ADD' | 'REMOVE' | 'SWAP' | 'SET' | 'SET_ALL' | 'UPDATE_AMOUNT' | 'CLEAR_ALL'; } -export const getItemFromContainer = (itemId: number, slot: number, container: ItemContainer): Item => { +export const getItemFromContainer = (itemId: number, slot: number, container: ItemContainer): Item | null => { if(slot < 0 || slot > container.items.length - 1) { return null; } @@ -25,10 +26,17 @@ export const getItemFromContainer = (itemId: number, slot: number, container: It return item; }; +/** + * This class represents a container of items. + * + * TODO (jameskmonger) We should use a Map instead of an array for the items. + */ +type InventoryMapType = (Item | null)[]; + export class ItemContainer { private readonly _size: number; - private readonly _items: Item[]; + private readonly _items: InventoryMapType; private readonly _containerUpdated: Subject; public constructor(size: number) { @@ -69,7 +77,14 @@ export class ItemContainer { search = search.itemId; } - const stackable = findItem(search).stackable; + const searchItem = findItem(search); + + if (!searchItem) { + logger.error(`Could not find item '${search}' when searching for items in container.`); + return []; + } + + const stackable = searchItem.stackable; if(stackable) { const index = this.findIndex(search); @@ -80,12 +95,12 @@ export class ItemContainer { return [ index ]; } } else { - const slots = []; + const slots: number[] = []; for(let i = 0; i < this.size; i++) { const item = this.items[i]; - if(hasValueNotNull(item) && item.itemId === search) { + if(item?.itemId === search) { slots.push(i); } } @@ -96,10 +111,10 @@ export class ItemContainer { public findIndex(item: number | Item): number { const itemId = (typeof item === 'number') ? item : item.itemId; - return this._items.findIndex(i => hasValueNotNull(i) && i.itemId === itemId); + return this._items.findIndex(i => i?.itemId === itemId); } - public setAll(items: Item[], fireEvent: boolean = true): void { + public setAll(items: (Item | null)[], fireEvent: boolean = true): void { for(let i = 0; i < this._size; i++) { this._items[i] = items[i]; } @@ -109,7 +124,7 @@ export class ItemContainer { } } - public set(slot: number, item: Item, fireEvent: boolean = true): void { + public set(slot: number, item: Item | null, fireEvent: boolean = true): void { this._items[slot] = item; if(fireEvent) { this._containerUpdated.next({ type: 'SET', slot, item }); @@ -118,9 +133,14 @@ export class ItemContainer { public findItemIndex(item: Item): number { for(let i = 0; i < this._size; i++) { - if(hasValueNotNull(this._items[i]) && - this._items[i].itemId === item.itemId && - this._items[i].amount >= item.amount) { + const inventoryItem = this._items[i]; + + if (inventoryItem === null) { + continue; + } + + if(inventoryItem.itemId === item.itemId && + inventoryItem.amount >= item.amount) { return i; } } @@ -128,7 +148,7 @@ export class ItemContainer { return -1; } - public add(item: number | string | Item, fireEvent: boolean = true): { item: Item, slot: number } { + public add(item: number | string | Item, fireEvent: boolean = true): { item: Item, slot: number } | null { if (typeof item === 'number') { item = { itemId: item, amount: 1 } as Item; } else if (typeof item === 'string') { @@ -144,10 +164,17 @@ export class ItemContainer { const existingItemIndex = this.findItemIndex({ itemId: item.itemId, amount: 1 }); const cacheItem = findItem(item.itemId); + if (!cacheItem) { + logger.error(`Could not find item '${item.itemId}' in cache when adding item to container.`); + return null; + } + if (existingItemIndex !== -1 && (cacheItem.stackable || cacheItem.bankNoteId != null)) { const newItem = { itemId: item.itemId, - amount: this._items[existingItemIndex].amount += item.amount + // using ! here because we know the item exists in the inventory + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + amount: this._items[existingItemIndex]!.amount += item.amount } as Item; this.set(existingItemIndex, newItem, false); @@ -176,7 +203,7 @@ export class ItemContainer { } } - public addStacking(item: number | Item, fireEvent: boolean = true): { item: Item, slot: number } { + public addStacking(item: number | Item, fireEvent: boolean = true): { item: Item, slot: number } | null { if (typeof item === 'number') { item = { itemId: item, amount: 1 } as Item; } @@ -186,7 +213,9 @@ export class ItemContainer { if (existingItemIndex !== -1) { const newItem = { itemId: item.itemId, - amount: this._items[existingItemIndex].amount += item.amount + // using ! here because we know the item exists in the inventory + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + amount: this._items[existingItemIndex]!.amount += item.amount } as Item; this.set(existingItemIndex, newItem, false); @@ -215,8 +244,8 @@ export class ItemContainer { } } - public amountInStack(index: number): number { - return this._items[index].amount; + public amountInStack(slot: number): number { + return this._items[slot]?.amount || 0; } public removeFirst(item: number | Item, fireEvent: boolean = true): number { @@ -234,7 +263,7 @@ export class ItemContainer { return slot; } - public remove(slot: number, fireEvent: boolean = true): Item { + public remove(slot: number, fireEvent: boolean = true): Item | null { const item = this._items[slot]; this._items[slot] = null; @@ -242,7 +271,6 @@ export class ItemContainer { this._containerUpdated.next({ type: 'REMOVE', slot }); } return item; - } public getFirstOpenSlot(): number { @@ -288,11 +316,12 @@ export class ItemContainer { let weight = 0; for(const item of this._items) { - if(!hasValueNotNull(item)) { + if(!item) { continue; } const itemData = findItem(item.itemId); + if(!itemData?.weight) { continue; } @@ -308,9 +337,11 @@ export class ItemContainer { if(!itemDefinition) { throw new Error(`Item ID ${ item.itemId } not found!`); } - if(itemDefinition.stackable || everythingStacks) { + if(itemDefinition.stackable || everythingStacks || fromNote(item) > -1) { if(this.has(item.itemId)) { - const invItem = this.items[this.findIndex(item.itemId)]; + // using ! here because we know that we have the item in the inventory + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const invItem = this.items[this.findIndex(item.itemId)]!; return invItem.amount + item.amount <= 2147483647; } return this.hasSpace(); @@ -324,7 +355,7 @@ export class ItemContainer { return this._size; } - public get items(): Item[] { + public get items(): (Item | null)[] { return this._items; } diff --git a/src/game-engine/world/items/item.ts b/src/engine/world/items/item.ts similarity index 92% rename from src/game-engine/world/items/item.ts rename to src/engine/world/items/item.ts index 42f25497d..a1903d3e9 100644 --- a/src/game-engine/world/items/item.ts +++ b/src/engine/world/items/item.ts @@ -1,5 +1,5 @@ -import { filestore } from '@engine/game-server'; -import { findItem, itemMap, widgets } from '@engine/config'; +import { filestore } from '@server/game/game-server'; +import { findItem, itemMap, widgets } from '@engine/config/config-handler'; import { ParentWidget, StaticItemWidget, WidgetBase } from '@runejs/filestore'; @@ -14,7 +14,7 @@ function itemInventoryOptions(itemId: number): string[] { return []; } - return itemDefinition.widgetOptions; + return itemDefinition.widgetOptions || []; } // TODO: Move to the filestore function IsParentWidget(widget: WidgetBase): widget is ParentWidget { @@ -33,7 +33,7 @@ export const getItemOptions = (itemId: number, widget: { widgetId: number, conta return itemInventoryOptions(itemId); } - let optionsWidget: StaticItemWidget; + let optionsWidget: StaticItemWidget | null = null; if (IsStaticItemWidget(widgetDefinition) && widgetDefinition.options && !widget.containerId) { optionsWidget = widgetDefinition; } diff --git a/src/game-engine/world/items/world-item.ts b/src/engine/world/items/world-item.ts similarity index 84% rename from src/game-engine/world/items/world-item.ts rename to src/engine/world/items/world-item.ts index b0177e469..58016fd15 100644 --- a/src/game-engine/world/items/world-item.ts +++ b/src/engine/world/items/world-item.ts @@ -3,7 +3,7 @@ import { Player } from '@engine/world/actor/player/player'; import { WorldInstance } from '@engine/world/instances'; -export class WorldItem { +export type WorldItem = { itemId: number; amount: number; position: Position; @@ -11,5 +11,5 @@ export class WorldItem { expires?: number; respawns?: number; removed?: boolean; - instance: WorldInstance = null; + instance: WorldInstance; } diff --git a/src/game-engine/world/map/chunk-manager.ts b/src/engine/world/map/chunk-manager.ts similarity index 89% rename from src/game-engine/world/map/chunk-manager.ts rename to src/engine/world/map/chunk-manager.ts index 4b7a40a85..7e0a79389 100644 --- a/src/game-engine/world/map/chunk-manager.ts +++ b/src/engine/world/map/chunk-manager.ts @@ -1,7 +1,7 @@ import { Chunk } from './chunk'; import { Position } from '../position'; -import { logger } from '@runejs/core'; -import { filestore } from '@engine/game-server'; +import { logger } from '@runejs/common'; +import { filestore } from '@server/game/game-server'; import { LandscapeFile, LandscapeObject, MapFile } from '@runejs/filestore'; @@ -84,10 +84,10 @@ export class ChunkManager { // Map region already registered return; } - this.regionMap.set(key, null); + this.regionMap.delete(key); - let mapFile: MapFile; - let landscapeFile: LandscapeFile; + let mapFile: MapFile | null = null; + let landscapeFile: LandscapeFile | null = null; try { mapFile = filestore.regionStore.getMapFile(mapRegionX, mapRegionY); @@ -100,6 +100,16 @@ export class ChunkManager { logger.error(`Error decoding landscape file ${mapRegionX},${mapRegionY}`); } + if(!mapFile) { + logger.error(`No decoded map file ${mapRegionX},${mapRegionY}`); + return; + } + + if(!landscapeFile) { + logger.error(`No decoded landscape file ${mapRegionX},${mapRegionY}`); + return; + } + const region: MapRegion = { mapFile, objects: landscapeFile?.landscapeObjects || [] }; this.regionMap.set(key, region); @@ -165,7 +175,9 @@ export class ChunkManager { const pos = (position as Position); if(this.chunkMap.has(pos.key)) { - return this.chunkMap.get(pos.key); + // using ! here because we know it exists + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return this.chunkMap.get(pos.key)!; } else { const chunk = new Chunk(pos); this.chunkMap.set(pos.key, chunk); diff --git a/src/game-engine/world/map/chunk.ts b/src/engine/world/map/chunk.ts similarity index 93% rename from src/game-engine/world/map/chunk.ts rename to src/engine/world/map/chunk.ts index 256239344..b3606ada4 100644 --- a/src/game-engine/world/map/chunk.ts +++ b/src/engine/world/map/chunk.ts @@ -1,10 +1,10 @@ import { Position } from '../position'; import { Player } from '../actor/player/player'; import { CollisionMap } from './collision-map'; -import { world } from '../../game-server'; -import { Npc } from '../actor/npc/npc'; +import { Npc } from '../actor/npc'; import { WorldItem } from '@engine/world/items/world-item'; import { LandscapeObject } from '@runejs/filestore'; +import { activeWorld } from '@engine/world'; interface CustomLandscapeObject { @@ -39,7 +39,7 @@ export class Chunk { public registerMapRegion(): void { const mapRegionX = Math.floor((this.position.x + 6) / 8); const mapRegionY = Math.floor((this.position.y + 6) / 8); - world.chunkManager.registerMapRegion(mapRegionX, mapRegionY); + activeWorld.chunkManager.registerMapRegion(mapRegionX, mapRegionY); } public setFilestoreLandscapeObject(landscapeObject: LandscapeObject): void { @@ -74,8 +74,8 @@ export class Chunk { } } - public getFilestoreLandscapeObject(objectId: number, position: Position): LandscapeObject { - return this.filestoreLandscapeObjects.get(`${position.x},${position.y},${objectId}`); + public getFilestoreLandscapeObject(objectId: number, position: Position): LandscapeObject | null { + return this.filestoreLandscapeObjects.get(`${position.x},${position.y},${objectId}`) || null; } public equals(chunk: Chunk): boolean { diff --git a/src/game-engine/world/map/collision-map.ts b/src/engine/world/map/collision-map.ts similarity index 95% rename from src/game-engine/world/map/collision-map.ts rename to src/engine/world/map/collision-map.ts index 5000e4187..50e62ab7d 100644 --- a/src/game-engine/world/map/collision-map.ts +++ b/src/engine/world/map/collision-map.ts @@ -1,7 +1,9 @@ import { Chunk } from './chunk'; -import { filestore, world } from '../../game-server'; +import { filestore } from '@server/game/game-server'; import { WorldInstance } from '@engine/world/instances'; import { LandscapeObject } from '@runejs/filestore'; +import { activeWorld } from '@engine/world'; +import { logger } from '@runejs/common'; /** * A map of collision masks for a chunk within the game world. @@ -16,9 +18,9 @@ export class CollisionMap { private _insetX: number; private _insetY: number; private _adjacency: number[][]; - private chunk: Chunk; - private instance: WorldInstance; - + private chunk: Chunk | null; + private instance: WorldInstance | null; + public constructor(x: number, y: number, heightLevel: number, options?: { chunk?: Chunk, instance?: WorldInstance }) { this.heightLevel = heightLevel; this.x = x; @@ -27,8 +29,8 @@ export class CollisionMap { this.sizeY = 8; this._insetX = (x + 6) * 8; this._insetY = (y + 6) * 8; - this.chunk = options?.chunk; - this.instance = options?.instance; + this.chunk = options?.chunk || null; + this.instance = options?.instance || null; this._adjacency = new Array(this.sizeX); for(let i = 0; i < this.sizeX; i++) { this._adjacency[i] = new Array(this.sizeY); @@ -43,6 +45,11 @@ export class CollisionMap { const objectOrientation = landscapeObject.orientation; const objectDetails = filestore.configStore.objectStore.getObject(landscapeObject.objectId); + if (!objectDetails) { + logger.error(`Could not find object details for object id: ${landscapeObject.objectId} when marking collision map.`); + return; + } + if(objectDetails.solid) { if(objectType === 22) { if(objectDetails.hasOptions) { @@ -60,19 +67,19 @@ export class CollisionMap { } } } - + public reset(): void { for(let x = 0; x < this.sizeX; x++) { for(let y = 0; y < this.sizeY; y++) { - this._adjacency[x][y] = this.chunk ? 0 : null; + this._adjacency[x][y] = 0; } } } - + public markWall(x: number, y: number, type: number, rotation: number, walkable: boolean): void { x -= this._insetX; y -= this._insetY; - + if(type == 0) { if(rotation == 0) { this.set(x, y, 128); @@ -315,7 +322,7 @@ export class CollisionMap { } } } - + public markSolidOccupant(occupantX: number, occupantY: number, width: number, height: number, rotation: number, walkable: boolean, mark: boolean): void { let occupied = 256; if(walkable) { @@ -356,7 +363,7 @@ export class CollisionMap { this._adjacency[x][y] &= 0xdfffff; } } - + public set(x: number, y: number, flag: number): void { let outOfBounds = false; @@ -391,7 +398,7 @@ export class CollisionMap { this._adjacency[x][y] |= flag; } } - + public unset(x: number, y: number, flag: number): void { let outOfBounds = false; @@ -419,9 +426,9 @@ export class CollisionMap { } } - public getSiblingCollisionMap(offsetX: number, offsetY: number): CollisionMap { + public getSiblingCollisionMap(offsetX: number, offsetY: number): CollisionMap | null { if(this.chunk) { - const offsetChunk: Chunk = world.chunkManager.getChunk({ + const offsetChunk: Chunk = activeWorld.chunkManager.getChunk({ x: this.chunk.position.x + offsetX, y: this.chunk.position.y + offsetY, level: this.heightLevel diff --git a/src/engine/world/map/index.ts b/src/engine/world/map/index.ts new file mode 100644 index 000000000..b719e064c --- /dev/null +++ b/src/engine/world/map/index.ts @@ -0,0 +1,5 @@ +export * from './chunk'; +export * from './chunk-manager'; +export * from './collision-map'; +export * from './landscape-object'; +export * from './region'; diff --git a/src/game-engine/world/map/landscape-object.ts b/src/engine/world/map/landscape-object.ts similarity index 100% rename from src/game-engine/world/map/landscape-object.ts rename to src/engine/world/map/landscape-object.ts diff --git a/src/game-engine/world/map/region.ts b/src/engine/world/map/region.ts similarity index 98% rename from src/game-engine/world/map/region.ts rename to src/engine/world/map/region.ts index 9ef505230..32d258fba 100644 --- a/src/game-engine/world/map/region.ts +++ b/src/engine/world/map/region.ts @@ -4,7 +4,6 @@ * chunk: 8x8 tile chunk within a map. */ import { Position } from '@engine/world/position'; -import { Room } from '@plugins/skills/construction/house'; export type RegionType = 'mapfile' | 'region' | 'chunk'; diff --git a/src/game-engine/world/position.ts b/src/engine/world/position.ts similarity index 93% rename from src/game-engine/world/position.ts rename to src/engine/world/position.ts index 9d4aa7efd..7a8190e45 100644 --- a/src/game-engine/world/position.ts +++ b/src/engine/world/position.ts @@ -1,6 +1,7 @@ import { Direction, directionData } from '@engine/world/direction'; -import { filestore } from '@engine/game-server'; +import { filestore } from '@server/game/game-server'; import { LandscapeObject } from '@runejs/filestore'; +import { logger } from '@runejs/common'; const directionDeltaX = [-1, 0, 1, -1, 1, -1, 0, 1]; @@ -34,7 +35,9 @@ export class Position { public constructor(x: number, y: number, level?: number); public constructor(arg0: number | Coords | Position, y?: number, level?: number) { if(typeof arg0 === 'number') { - this.move(arg0, y, level); + // using ! here, because we know that if arg0 is a number, then y and level are numbers + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.move(arg0, y!, level); } else { this.move(arg0.x, arg0.y, arg0.level); } @@ -52,10 +55,15 @@ export class Position { return this.distanceBetween(target) <= minimumDistance; } else { const definition = filestore.configStore.objectStore.getObject(target.objectId); + + if (!definition) { + logger.warn(`Object with id ${target.objectId} does not exist in the object store.`); + } + const occupantX = target.x; const occupantY = target.y; - let width = definition.rendering?.sizeX || 1; - let height = definition.rendering?.sizeY || 1; + let width = definition?.rendering?.sizeX || 1; + let height = definition?.rendering?.sizeY || 1; if(width === undefined || width === null || width < 1) { width = 1; diff --git a/src/game-engine/world/skill-util/glory-boost.ts b/src/engine/world/skill-util/glory-boost.ts similarity index 100% rename from src/game-engine/world/skill-util/glory-boost.ts rename to src/engine/world/skill-util/glory-boost.ts diff --git a/src/game-engine/world/skill-util/harvest-roll.ts b/src/engine/world/skill-util/harvest-roll.ts similarity index 100% rename from src/game-engine/world/skill-util/harvest-roll.ts rename to src/engine/world/skill-util/harvest-roll.ts diff --git a/src/game-engine/world/skill-util/harvest-skill.ts b/src/engine/world/skill-util/harvest-skill.ts similarity index 83% rename from src/game-engine/world/skill-util/harvest-skill.ts rename to src/engine/world/skill-util/harvest-skill.ts index 48c7fd862..a6483a669 100644 --- a/src/game-engine/world/skill-util/harvest-skill.ts +++ b/src/engine/world/skill-util/harvest-skill.ts @@ -2,16 +2,23 @@ import { Player } from '@engine/world/actor/player/player'; import { IHarvestable } from '@engine/world/config/harvestable-object'; import { soundIds } from '@engine/world/config/sound-ids'; import { Skill } from '@engine/world/actor/skills'; -import { loopingEvent, world } from '@engine/game-server'; import { getBestAxe, getBestPickaxe, HarvestTool } from '@engine/world/config/harvest-tool'; import { randomBetween } from '@engine/util/num'; -import { ObjectInteractionAction } from '@engine/world/action/object-interaction.action'; +import { ObjectInteractionAction } from '@engine/action'; import { colors } from '@engine/util/colors'; import { checkForGemBoost } from '@engine/world/skill-util/glory-boost'; import { colorText } from '@engine/util/strings'; import { rollBirdsNestType, rollGemRockResult, rollGemType } from '@engine/world/skill-util/harvest-roll'; -import { findItem } from '@engine/config'; - +import { findItem } from '@engine/config/config-handler'; +import { activeWorld } from '@engine/world'; +import { loopingEvent } from '@engine/plugins'; +import { logger } from '@runejs/common'; + +/** + * Check if a player can harvest a given {@link IHarvestable} + * + * @returns a {@link HarvestTool} if the player can harvest the object, or undefined if they cannot. + */ export function canInitiateHarvest(player: Player, target: IHarvestable, skill: Skill): undefined | HarvestTool { if (!target) { switch (skill) { @@ -28,7 +35,14 @@ export function canInitiateHarvest(player: Player, target: IHarvestable, skill: return; } - let targetName: string = findItem(target.itemId).name.toLowerCase(); + const item = findItem(target.itemId); + if (!item) { + logger.error(`Could not find item with id ${target.itemId} for harvestable object.`); + player.sendMessage('Sorry, there was an error. Please contact a developer.'); + return; + } + + let targetName = item.name.toLowerCase(); switch (skill) { case Skill.MINING: targetName = targetName.replace(' ore', ''); @@ -88,7 +102,13 @@ export function handleHarvesting(details: ObjectInteractionAction, tool: Harvest if (details.object.objectId === 2111 && details.player.skills.hasLevel(Skill.MINING, 30)) { itemToAdd = rollGemRockResult().itemId; } - let targetName: string = findItem(itemToAdd).name.toLowerCase(); + const item = findItem(target.itemId); + if (!item) { + logger.error(`Could not find item with id ${target.itemId} for harvestable object.`); + return; + } + + let targetName = item.name.toLowerCase(); switch (skill) { case Skill.MINING: @@ -139,7 +159,7 @@ export function handleHarvesting(details: ObjectInteractionAction, tool: Harvest if (roll === 1) { randomLoot = true; details.player.sendMessage(colorText('A bird\'s nest falls out of the tree.', colors.red)); - world.globalInstance.spawnWorldItem(rollBirdsNestType(), details.player.position, + activeWorld.globalInstance.spawnWorldItem(rollBirdsNestType(), details.player.position, { owner: details.player, expires: 300 }); } break; @@ -160,10 +180,17 @@ export function handleHarvesting(details: ObjectInteractionAction, tool: Harvest details.player.skills.addExp(skill, target.experience); if (randomBetween(0, 100) <= target.break) { details.player.playSound(soundIds.oreDepeleted); - details.player.instance.replaceGameObject(target.objects.get(details.object.objectId), - details.object, randomBetween(target.respawnLow, target.respawnHigh)); - loop.cancel(); + + const replacementObject = target.objects.get(details.object.objectId); + const respawnTime = randomBetween(target.respawnLow, target.respawnHigh); + + if (replacementObject) { + details.player.instance.replaceGameObject(replacementObject, details.object, respawnTime); + } + details.player.playAnimation(null); + + loop.cancel(); return; } } else { @@ -191,5 +218,7 @@ export function handleHarvesting(details: ObjectInteractionAction, tool: Harvest } elapsedTicks++; }, () => { - }, () => details.player.playAnimation(null)); + }, () => { + details.player.playAnimation(null); + }); } diff --git a/src/engine/world/sound/index.ts b/src/engine/world/sound/index.ts new file mode 100644 index 000000000..e57a053e6 --- /dev/null +++ b/src/engine/world/sound/index.ts @@ -0,0 +1 @@ +export * from './music'; diff --git a/src/engine/world/sound/music.ts b/src/engine/world/sound/music.ts new file mode 100644 index 000000000..a28c6917b --- /dev/null +++ b/src/engine/world/sound/music.ts @@ -0,0 +1,15 @@ +export enum MusicPlayerMode { + MANUAL = 0, + AUTO = 1 +} + +export enum MusicPlayerLoopMode { + ENABLED = 0, + DISABLED = 1 +} + +export enum MusicTabButtonIds { + AUTO_BUTTON_ID = 180, + MANUAL_BUTTON_ID = 181, + LOOP_BUTTON_ID = 251 +} diff --git a/src/game-engine/world/task.ts b/src/engine/world/task.ts similarity index 88% rename from src/game-engine/world/task.ts rename to src/engine/world/task.ts index e525ee510..2d7a35f89 100644 --- a/src/game-engine/world/task.ts +++ b/src/engine/world/task.ts @@ -1,5 +1,5 @@ import { lastValueFrom, timer } from 'rxjs'; -import { World } from '@engine/world/index'; +import { World } from '@engine/world'; import { take } from 'rxjs/operators'; diff --git a/src/game-engine/world/index.ts b/src/engine/world/world.ts similarity index 82% rename from src/game-engine/world/index.ts rename to src/engine/world/world.ts index 1bf0aa054..9beb90c3f 100644 --- a/src/game-engine/world/index.ts +++ b/src/engine/world/world.ts @@ -1,26 +1,20 @@ -import { logger } from '@runejs/core'; import Quadtree from 'quadtree-lib'; -import { Player } from './actor/player/player'; -import { ChunkManager } from './map/chunk-manager'; -import { ExamineCache } from './config/examine-data'; -import { loadPlugins, world } from '@engine/game-server'; -import { Position } from './position'; -import { Npc } from './actor/npc/npc'; -import TravelLocations from '@engine/world/config/travel-locations'; -import { Actor } from '@engine/world/actor/actor'; -import { schedule } from '@engine/world/task'; -import { parseScenerySpawns } from '@engine/world/config/scenery-spawns'; -import { findItem, findNpc, findObject, itemSpawns, npcSpawns } from '@engine/config'; -import { NpcDetails } from '@engine/config/npc-config'; -import { WorldInstance } from '@engine/world/instances'; -import { Direction } from '@engine/world/direction'; -import { NpcSpawn } from '@engine/config/npc-spawn-config'; -import { loadActionFiles } from '@engine/world/action'; -import { LandscapeObject } from '@runejs/filestore'; +import uuidv4 from 'uuid/v4'; import { lastValueFrom, Subject } from 'rxjs'; import { take } from 'rxjs/operators'; -import { ConstructedRegion, getTemplateLocalX, getTemplateLocalY } from '@engine/world/map/region'; -import { Chunk } from '@engine/world/map/chunk'; + +import { logger } from '@runejs/common'; +import { LandscapeObject } from '@runejs/filestore'; + +import { schedule, WorldInstance, Direction, Position, activeWorld } from '@engine/world'; +import { findItem, findNpc, findObject, itemSpawns, npcSpawns, NpcDetails, NpcSpawn } from '@engine/config'; +import { Player, Npc, Actor } from '@engine/world/actor'; +import { loadActionFiles } from '@engine/action'; +import { ChunkManager, ConstructedRegion, getTemplateLocalX, getTemplateLocalY } from '@engine/world/map'; +import { TravelLocations, ExamineCache, parseScenerySpawns } from '@engine/world/config'; +import { loadPlugins } from '@engine/plugins'; +import { TaskScheduler, Task } from '@engine/task'; +import { Isaac } from '@engine/net'; export interface QuadtreeKey { @@ -46,8 +40,9 @@ export class World { public readonly travelLocations: TravelLocations = new TravelLocations(); public readonly playerTree: Quadtree; public readonly npcTree: Quadtree; - public readonly globalInstance = new WorldInstance(); + public readonly globalInstance = new WorldInstance(uuidv4()); public readonly tickComplete: Subject = new Subject(); + private readonly scheduler = new TaskScheduler(); private readonly debugCycleDuration: boolean = process.argv.indexOf('-tickTime') !== -1; @@ -65,7 +60,7 @@ export class World { this.setupWorldTick(); } - public async init(): Promise { + public async startup(): Promise { await loadPlugins(); await loadActionFiles(); this.spawnGlobalNpcs(); @@ -73,6 +68,24 @@ export class World { this.spawnScenery(); } + public shutdown(): void { + this.kickAllPlayers(); + logger.info(`Shutting down world...`); + } + + /** + * Adds a task to the world scheduler queue. These tasks will run forever until they are cancelled. + * + * @warning Did you mean to add a world task, rather than an Actor task? + * + * If the task has a stack type of `NEVER`, other tasks in the same group will be cancelled. + * + * @param task The task to add + */ + public enqueueTask(task: Task): void { + this.scheduler.enqueue(task); + } + /** * Searched for an object by ID at the given position in any of the player's active instances. * @param actor The actor to find the object for. @@ -80,7 +93,7 @@ export class World { * @param objectPosition The game world position that the object is expected at. */ public findObjectAtLocation(actor: Actor, objectId: number, - objectPosition: Position): { object: LandscapeObject, cacheOriginal: boolean } { + objectPosition: Position): { object: LandscapeObject | null, cacheOriginal: boolean } { const x = objectPosition.x; const y = objectPosition.y; @@ -101,7 +114,13 @@ export class World { let personalTileModifications; if(actor.isPlayer) { - tileModifications = (actor as Player).instance.getTileModifications(objectPosition); + const instance = (actor as Player).instance; + + if (!instance) { + throw new Error(`Player ${(actor as Player).username} has no instance.`); + } + + tileModifications = instance.getTileModifications(objectPosition); personalTileModifications = (actor as Player).personalInstance.getTileModifications(objectPosition); } else { tileModifications = this.globalInstance.getTileModifications(objectPosition); @@ -162,7 +181,7 @@ export class World { } const objectChunk = this.chunkManager.getChunkForWorldPosition(objectPosition); - const mapChunk = world.chunkManager.getChunkForWorldPosition(map.renderPosition); + const mapChunk = activeWorld.chunkManager.getChunkForWorldPosition(map.renderPosition); const chunkIndexX = objectChunk.position.x - (mapChunk.position.x - 2); const chunkIndexY = objectChunk.position.y - (mapChunk.position.y - 2); @@ -178,7 +197,7 @@ export class World { const mapTemplateWorldX = tileX; const mapTemplateWorldY = tileY; - const mapTemplateChunk = world.chunkManager.getChunkForWorldPosition(new Position(mapTemplateWorldX, mapTemplateWorldY, objectPosition.level)); + const mapTemplateChunk = activeWorld.chunkManager.getChunkForWorldPosition(new Position(mapTemplateWorldX, mapTemplateWorldY, objectPosition.level)); const templateLocalX = getTemplateLocalX(tileOrientation, objectLocalX, objectLocalY, objectConfig?.rendering?.sizeX || 1, objectConfig?.rendering?.sizeY || 1); @@ -207,6 +226,24 @@ export class World { return realObject || null; } + /** + * Saves player data for every active player within the game world before logging + * them out for a gentle game server shutdown. + */ + public kickAllPlayers(): void { + if(!this.playerList) { + return; + } + + logger.info(`Kicking all players...`); + + this.playerList + .filter(player => player !== null) + .forEach(player => player.logout()); + + logger.info(`Player data save complete, world is now empty.`); + } + /** * Saves player data for every active player within the game world. */ @@ -231,8 +268,8 @@ export class World { * @param volume The volume the sound should play at. * @param distance The distance which the sound should reach. */ - public playLocationSound(position: Position, soundId: number, volume: number, distance: number = 10): void { - this.findNearbyPlayers(position, distance).forEach(player => { + public playLocationSound(position: Position, instanceId: string, soundId: number, volume: number, distance: number = 10): void { + this.findNearbyPlayers(position, distance, instanceId).forEach(player => { player.outgoingPackets.updateReferencePosition(position); player.outgoingPackets.playSoundAtPosition( soundId, @@ -250,7 +287,7 @@ export class World { * @param distance The maximum distance to search for NPCs. * @param instanceId The NPC's active instance. */ - public findNearbyNpcsById(position: Position, npcId: number, distance: number, instanceId: string = null): Npc[] { + public findNearbyNpcsById(position: Position, npcId: number, distance: number, instanceId: string | null = null): Npc[] { return this.npcTree.colliding({ x: position.x - (distance / 2), y: position.y - (distance / 2), @@ -264,7 +301,7 @@ export class World { * @param npcKey The Key of the NPCs to find. * @param instanceId The NPC's active instance. */ - public findNpcsByKey(npcKey: string, instanceId: string = null): Npc[] { + public findNpcsByKey(npcKey: string, instanceId: string | null = null): Npc[] { return this.npcList.filter(npc => npc && npc.key === npcKey && npc.instanceId === instanceId); } @@ -273,7 +310,7 @@ export class World { * @param npcId The ID of the NPCs to find. * @param instanceId The NPC's active instance. */ - public findNpcsById(npcId: number, instanceId: string = null): Npc[] { + public findNpcsById(npcId: number, instanceId: string | null = null): Npc[] { return this.npcList.filter(npc => npc && npc.id === npcId && npc.instanceId === instanceId); } @@ -291,7 +328,7 @@ export class World { * @param distance The maximum distance to search for NPCs. * @param instanceId The NPC's active instance. */ - public findNearbyNpcs(position: Position, distance: number, instanceId: string = null): Npc[] { + public findNearbyNpcs(position: Position, distance: number, instanceId: string | null = null): Npc[] { return this.npcTree.colliding({ x: position.x - (distance / 2), y: position.y - (distance / 2), @@ -306,7 +343,7 @@ export class World { * @param distance The maximum distance to search for Players. * @param instanceId The player's active instance. */ - public findNearbyPlayers(position: Position, distance: number, instanceId: string = null): Player[] { + public findNearbyPlayers(position: Position, distance: number, instanceId: string): Player[] { return this.playerTree.colliding({ x: position.x - (distance / 2), y: position.y - (distance / 2), @@ -314,17 +351,19 @@ export class World { height: distance }) .map(quadree => quadree.actor as Player) - .filter(player => player.personalInstance.instanceId === instanceId || - player.instance.instanceId === instanceId); + .filter(player => ( + player.personalInstance.instanceId === instanceId + || player.instance?.instanceId === instanceId + )); } /** * Finds a logged in player via their username. * @param username The player's username. */ - public findActivePlayerByUsername(username: string): Player { + public findActivePlayerByUsername(username: string): Player | null { username = username.toLowerCase(); - return this.playerList.find(p => p && p.username.toLowerCase() === username); + return this.playerList.find(p => p && p.username.toLowerCase() === username) || null; } /** @@ -358,25 +397,19 @@ export class World { } public async spawnNpc(npcKey: string | number, position: Position, face: Direction, - movementRadius: number = 0, instanceId: string = null): Promise { + movementRadius: number = 0, instanceId: string | null = null): Promise { if(!npcKey) { - return null; + throw new Error('NPC key must be provided.'); } - let npcData: NpcDetails | number = findNpc(npcKey); + const npcData = findNpc(npcKey); if(!npcData) { - logger.warn(`NPC ${npcKey} not yet registered on the server.`); - - if(typeof npcKey === 'number') { - npcData = npcKey; - } else { - return null; - } + throw new Error(`NPC ${npcKey} not found in the cache`); } const npc = new Npc(npcData, new NpcSpawn(typeof npcData === 'number' ? `unknown_${npcData}` : npcData.key, - position, movementRadius, face), instanceId); + position, movementRadius, face)); await this.registerNpc(npc); @@ -402,7 +435,8 @@ export class World { const spawnChunk = this.chunkManager.getChunkForWorldPosition(new Position(x, y, 0)); for(let i = 0; i < 1000; i++) { - const player = new Player(null, null, null, i, `test${i}`, 'abs', true); + // TODO (Jameskmonger) we should be able to create a player without a connection, and without passing nulls in + const player = new Player(null as any, null as any, null as any, i, `test${i}`, 'abs', true); this.registerPlayer(player); player.interfaceState.closeAllSlots(); @@ -427,6 +461,9 @@ export class World { public async worldTick(): Promise { const hrStart = Date.now(); + + this.scheduler.tick(); + const activePlayers: Player[] = this.playerList.filter(player => player !== null); if(activePlayers.length === 0) { @@ -474,7 +511,7 @@ export class World { return this.playerList.filter(player => !player).length; } - public findPlayer(playerUsername: string): Player { + public findPlayer(playerUsername: string): Player | null { playerUsername = playerUsername.toLowerCase(); return this.playerList?.find(p => p !== null && p.username.toLowerCase() === playerUsername) || null; } @@ -520,7 +557,7 @@ export class World { * @param player The player to remove from the world list. */ public deregisterPlayer(player: Player): void { - this.playerList[player.worldIndex] = null; + delete this.playerList[player.worldIndex]; } public npcExists(npc: Npc): boolean { @@ -552,7 +589,7 @@ export class World { public deregisterNpc(npc: Npc): void { npc.exists = false; - this.npcList[npc.worldIndex] = null; + delete this.npcList[npc.worldIndex]; } } diff --git a/src/game-engine/game-server.ts b/src/game-engine/game-server.ts deleted file mode 100644 index 4f2b00b77..000000000 --- a/src/game-engine/game-server.ts +++ /dev/null @@ -1,253 +0,0 @@ -import { World } from './world'; -import { logger } from '@runejs/core'; -import { parseServerConfig } from '@runejs/core/net'; -import { Filestore, LandscapeObject } from '@runejs/filestore'; - -import { ServerConfig } from '@engine/config/server-config'; -import { loadPluginFiles } from '@engine/plugins/content-plugin'; -import { loadPackets } from '@engine/net/inbound-packets'; -import { watchForChanges, watchSource } from '@engine/util/files'; -import { openGameServer } from '@engine/net/server/game-server'; -import { loadCoreConfigurations, loadGameConfigurations, xteaRegions } from '@engine/config'; -import { Quest } from '@engine/world/actor/player/quest'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { Player } from '@engine/world/actor/player/player'; -import { Subject, timer } from 'rxjs'; -import { Position } from '@engine/world/position'; -import { ActionHook, sortActionHooks } from '@engine/world/action/hooks'; -import { ActionType } from '@engine/world/action'; - - -/** - * The singleton instance containing the server's active configuration settings. - */ -export let serverConfig: ServerConfig; - - -/** - * The singleton instance referencing the game's asset filestore. - */ -export let filestore: Filestore; - - -/** - * The singleton instance of this game world. - */ -export let world: World; - - -/** - * A type for describing the plugin action hook map. - */ -type PluginActionHookMap = { - [key in ActionType]?: ActionHook[]; -}; - - -/** - * A type for describing the plugin action hook map. - */ -interface PluginQuestMap { - [key: string]: Quest; -} - - -/** - * A list of action hooks imported from content plugins. - */ -export let actionHookMap: PluginActionHookMap = {}; - - -/** - * A list of quests imported from content plugins. - */ -export let questMap: PluginQuestMap = {}; - - -/** - * Searches for and loads all plugin files and their associated action hooks. - */ -export async function loadPlugins(): Promise { - actionHookMap = {}; - questMap = {}; - const plugins = await loadPluginFiles(); - - const pluginActionHookList = plugins?.filter(plugin => !!plugin?.hooks)?.map(plugin => plugin.hooks); - - if(pluginActionHookList && pluginActionHookList.length !== 0) { - pluginActionHookList.reduce( - (a, b) => a.concat(b))?.forEach(action => { - if(!(action instanceof Quest)) { - if(!actionHookMap[action.type]) { - actionHookMap[action.type] = []; - } - - actionHookMap[action.type].push(action); - } else { - if(!actionHookMap['quest']) { - actionHookMap['quest'] = []; - } - - actionHookMap['quest'].push(action); - } - }); - } else { - logger.warn(`No action hooks detected - update plugins.`); - } - - const pluginQuestList = plugins?.filter(plugin => !!plugin?.quests)?.map(plugin => plugin.quests); - - if(pluginQuestList && pluginQuestList.length > 0) { - pluginQuestList.reduce((prev, curr) => prev.concat(curr)) - .forEach(quest => questMap[quest.id] = quest); - } - - // @TODO implement proper sorting rules - Object.keys(actionHookMap) - .forEach(key => actionHookMap[key] = - sortActionHooks(actionHookMap[key])); -} - - -/** - * Configures the game server, parses the asset filestore, - * awakens the game world, and finally initializes the - * game socket server. - */ -export async function runGameServer(): Promise { - serverConfig = parseServerConfig(); - - if(!serverConfig) { - logger.error('Unable to start server due to missing or invalid server configuration.'); - return; - } - - await loadCoreConfigurations(); - filestore = new Filestore('cache', { xteas: xteaRegions }); - - await loadGameConfigurations(); - - await loadPackets(); - - world = new World(); - await world.init(); - - if(process.argv.indexOf('-fakePlayers') !== -1) { - world.generateFakePlayers(); - } - - openGameServer(serverConfig.host, serverConfig.port); - - watchSource('src/').subscribe(() => world.saveOnlinePlayers()); - watchForChanges('dist/plugins/', /[/\\]plugins[/\\]/); -} - - - -/** - * A type of action that loops until either one of three things happens: - * 1. A player is specified within `options` who's `actionsCancelled` event has been fired during the loop. - * 2. An npc is specified within `options` who no longer exists at some point during the loop. - * 3. The `cancel()` function is manually called, presumably when the purpose of the loop has been completed. - * @param options Options to provide to the looping action, which include: - * `ticks` the number of game ticks between loop cycles. Defaults to 1 game tick between loops. - * `delayTicks` the number of game ticks to wait before starting the first loop. Defaults to 0 game ticks. - * `player` the player that the loop belongs to. Providing this field will cause the loop to cancel if this - * player's `actionsCancelled` is fired during the loop. - * `npc` the npc that the loop belongs to. This will Providing this field will cause the loop to cancel if - * this npc is flagged to no longer exist during the loop. - * @deprecated - use new Action Hook task system instead. - */ -export const loopingEvent = (options?: { - ticks?: number; - delayTicks?: number; - npc?: Npc; - player?: Player; -}): { event: Subject, cancel: () => void } => { - if(!options) { - options = {}; - } - - const { ticks, delayTicks, npc, player } = options; - const event: Subject = new Subject(); - - const subscription = timer(delayTicks === undefined ? 0 : (delayTicks * World.TICK_LENGTH), - ticks === undefined ? World.TICK_LENGTH : (ticks * World.TICK_LENGTH)).subscribe(() => { - if(npc && !npc.exists) { - event.complete(); - subscription.unsubscribe(); - return; - } - - event.next(); - }); - - let actionCancelled; - - if(player) { - actionCancelled = player.actionsCancelled.subscribe(() => { - subscription.unsubscribe(); - actionCancelled.unsubscribe(); - event.complete(); - }); - } - - return { - event, cancel: () => { - subscription.unsubscribe(); - - if(actionCancelled) { - actionCancelled.unsubscribe(); - } - - event.complete(); - } - }; -}; - - -/** - * A walk-to type of action that requires the specified player to walk to a specific destination before proceeding. - * Note that this does not force the player to walk, it simply checks to see if the player is walking where specified. - * @param player The player that must walk to a specific position. - * @param position The position that the player needs to end up at. - * @param interactingAction [optional] The information about the interaction that the player is making. Not required. - * @deprecated - use methods provided within the Actor API to force or await movement - */ -export const playerWalkTo = async (player: Player, position: Position, interactingAction?: { - interactingObject?: LandscapeObject; -}): Promise => { - return new Promise((resolve, reject) => { - player.metadata.walkingTo = position; - - const inter = setInterval(() => { - if(!player.metadata.walkingTo || !player.metadata.walkingTo.equals(position)) { - reject(); - clearInterval(inter); - return; - } - - if(!player.walkingQueue.moving()) { - if(!interactingAction) { - if(player.position.distanceBetween(position) > 1) { - reject(); - } else { - resolve(); - } - } else { - if(interactingAction.interactingObject) { - const locationObject = interactingAction.interactingObject; - if(player.position.withinInteractionDistance(locationObject)) { - resolve(); - } else { - reject(); - } - } - } - - clearInterval(inter); - player.metadata.walkingTo = null; - } - }, 100); - }); -}; diff --git a/src/game-engine/login-server.ts b/src/game-engine/login-server.ts deleted file mode 100644 index 356d7bf08..000000000 --- a/src/game-engine/login-server.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { launchLoginServer } from '@runejs/login-server'; -import 'source-map-support/register'; - -launchLoginServer(); diff --git a/src/game-engine/net/inbound-packets/add-friend-packet.js b/src/game-engine/net/inbound-packets/add-friend-packet.js deleted file mode 100644 index 0899340b3..000000000 --- a/src/game-engine/net/inbound-packets/add-friend-packet.js +++ /dev/null @@ -1,7 +0,0 @@ -import { longToString } from '../../util/strings'; - -export default { - opcode: 114, - size: 8, - handler: (player, packet) => player.addFriend(longToString(packet.buffer.get('LONG'))) -}; diff --git a/src/game-engine/net/inbound-packets/add-ignore-packet.js b/src/game-engine/net/inbound-packets/add-ignore-packet.js deleted file mode 100644 index 183b0b2b3..000000000 --- a/src/game-engine/net/inbound-packets/add-ignore-packet.js +++ /dev/null @@ -1,7 +0,0 @@ -import { longToString } from '../../util/strings'; - -export default { - opcode: 251, - size: 8, - handler: (player, packet) => player.addIgnoredPlayer(longToString(packet.buffer.get('LONG'))) -}; diff --git a/src/game-engine/net/inbound-packets/blinking-tab-click-packet.js b/src/game-engine/net/inbound-packets/blinking-tab-click-packet.js deleted file mode 100644 index 1894861bc..000000000 --- a/src/game-engine/net/inbound-packets/blinking-tab-click-packet.js +++ /dev/null @@ -1,16 +0,0 @@ -const blinkingTabClickPacket = (player, packet) => { - const { buffer } = packet; - const tabIndex = buffer.get(); - - const tabClickEventIndex = player.metadata?.tabClickEvent?.tabIndex || -1; - - if(tabClickEventIndex === tabIndex) { - player.metadata.tabClickEvent.event.next(true); - } -}; - -export default { - opcode: 44, - size: 1, - handler: blinkingTabClickPacket -}; diff --git a/src/game-engine/net/inbound-packets/number-input-packet.js b/src/game-engine/net/inbound-packets/number-input-packet.js deleted file mode 100644 index dc7abaa1d..000000000 --- a/src/game-engine/net/inbound-packets/number-input-packet.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - opcode: 238, - size: 4, - handler: (player, packet) => - player.numericInputEvent.next(packet.buffer.get('int', 'u')) -}; diff --git a/src/game-engine/net/inbound-packets/remove-friend-packet.js b/src/game-engine/net/inbound-packets/remove-friend-packet.js deleted file mode 100644 index 48f1f09fc..000000000 --- a/src/game-engine/net/inbound-packets/remove-friend-packet.js +++ /dev/null @@ -1,16 +0,0 @@ -import { longToString } from '../../util/strings'; -import { PrivateMessaging } from '../../world/actor/player/private-messaging'; - -export default { - opcode: 255, - size: 8, - handler: (player, packet) => { - const friendName = longToString(packet.buffer.get('long')); - if(!friendName) { - return; - } - - player.removeFriend(friendName); - PrivateMessaging.friendRemoved(player, friendName); - } -}; diff --git a/src/game-engine/net/inbound-packets/social-button-packet.js b/src/game-engine/net/inbound-packets/social-button-packet.js deleted file mode 100644 index 6ba5edb2c..000000000 --- a/src/game-engine/net/inbound-packets/social-button-packet.js +++ /dev/null @@ -1,19 +0,0 @@ -import { PrivateMessaging } from '../../world/actor/player/private-messaging'; - -export default { - opcode: 32, - size: 3, - handler: (player, packet) => { - const { buffer } = packet; - - const currentPrivateChatMode = player.settings.privateChatMode; - - player.settings.publicChatMode = buffer.get(); - player.settings.privateChatMode = buffer.get(); - player.settings.tradeMode = buffer.get(); - - if(currentPrivateChatMode !== player.settings.privateChatMode) { - PrivateMessaging.playerPrivateChatModeChanged(player); - } - } -}; diff --git a/src/game-engine/update-server.ts b/src/game-engine/update-server.ts deleted file mode 100644 index c1919b642..000000000 --- a/src/game-engine/update-server.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { launchUpdateServer } from '@runejs/update-server'; -import 'source-map-support/register'; - -launchUpdateServer(); diff --git a/src/game-engine/util/directories.ts b/src/game-engine/util/directories.ts deleted file mode 100644 index 7b4207042..000000000 --- a/src/game-engine/util/directories.ts +++ /dev/null @@ -1 +0,0 @@ -export const gameEngineDist = './dist/game-engine'; diff --git a/src/game-engine/world/actor/behaviors/auto-attack.behavior.ts b/src/game-engine/world/actor/behaviors/auto-attack.behavior.ts deleted file mode 100644 index f50991cef..000000000 --- a/src/game-engine/world/actor/behaviors/auto-attack.behavior.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Actor } from '../actor'; -import { regionChangeActionFactory } from '@engine/world/action/region-change.action'; -import { Subject } from 'rxjs'; -import { logger } from '@runejs/core'; -import { Behavior, BehaviorType } from './behavior'; -import { Timestamp } from 'rxjs/dist/types/internal/types'; -import { timestamp } from 'rxjs/dist/types/operators'; -import { Npc } from '../npc/npc'; -import { Player } from '../player/player'; - -export class AutoAttackBehavior extends Behavior { - - Type = BehaviorType.Combat; - Name = 'auto-attack-combat'; - - private _combatPulse; - private _CoolDown: number = 3; - private _lastAttack = new Date(); - private _player: Player; - - //this should be called when combat starts - public async init(me: Actor, them: Actor): Promise { - this.Me = me; - this.Them = them; - this._player = (me as Player); - console.log('all set to auto attack!'); - (this.Them as Npc).npcEvents.on('death', (npc) => this._player.onNpcKill); - await super.init(me, them); - } - - public async tick() { - if (this.Me == null) return; - - return new Promise(resolve => { - //only use boolean checks in behaviors never calculated values if you can help it (performance) - if (this.Me.inCombat) { - if (this.Them.isDead) { - //ToDo: this is the last one on the stack not neccessarily your current target. - this.Me.combatTargets.pop(); - resolve(); - return; - } - if (this.Distance > 25) { - this.Me.inCombat = false; - console.log('target too far away - ending combat'); - resolve(); - } - - //If we are not in range move there - if (this.Distance > this.Me.meleeDistance) this.Me.moveTo(this.Them); - //Are you in range to attack? - if (this.Distance <= this.Me.meleeDistance && this.coolDownElapsed) { - this.doAttack(); - this.resetCoolDown(this._CoolDown); - } - - if (!this.Me.isDead) super.tick(); - resolve(); - } - - - }); - } - public async doAttack(): Promise { - return new Promise(resolve => { - //do attack stuff - const attack = this.Me.getAttackRoll(this.Them); - console.log(`you attack ${(this.Them as Npc).name} for ${attack.damage} damage! (after the CD)`); - this.Them.damage(attack.damage); - if (this.Them.hitPoints <= 0) { - (this.Them as Npc).npcEvents.emit('death', this.Me, this.Them); - } - - }); - } - public get coolDownElapsed(): boolean { - if (new Date() > this._lastAttack) return true; - return false; - } - public resetCoolDown(seconds: number): void { - this._lastAttack.setSeconds(this._lastAttack.getSeconds() + seconds); - } - - -} \ No newline at end of file diff --git a/src/game-engine/world/actor/behaviors/behavior.ts b/src/game-engine/world/actor/behaviors/behavior.ts deleted file mode 100644 index 7f5c4bfdc..000000000 --- a/src/game-engine/world/actor/behaviors/behavior.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Actor } from '../actor'; -import { regionChangeActionFactory } from '@engine/world/action/region-change.action'; -import { Subject } from 'rxjs'; -import { Npc } from '../npc/npc'; -import { Player } from '../player/player'; - -export abstract class Behavior { - //because not all interaction between npcs will be combat oriented me/them is on the base class - public Me: Actor; - public Them: Actor; - public Distance: number; - public Name: string; - public Type: BehaviorType; - //Be sure to call the tick super so you wont have to duplicate all the functionality - public async tick() { - if (this.Me.isDead) return; - //If we have more than one combat target be sure to select the next one - if (this.Them == null && this.Me != null && this.Me.combatTargets.length > 0) this.Them == this.Me.combatTargets[0]; - //update calculated variables - if (this.Them != null) this.Distance = this.Me.position.distanceBetween(this.Them.position); - - return new Promise(resolve => { resolve(); }); - } - public async init(me: Actor = null, them: Actor = null) { - if (me != null && them != null) me.combatTargets.push(them); - return new Promise(resolve => { - resolve(); - }); - } -} - - -export enum BehaviorType { - //movement - Roaming = 'roaming', //world.tickComplete - Chase = 'chase', //position.distanceBetween - //combat - Combat = 'combat', - Flee = 'flee', - -} \ No newline at end of file diff --git a/src/game-engine/world/actor/behaviors/melee-combat.behavior.ts b/src/game-engine/world/actor/behaviors/melee-combat.behavior.ts deleted file mode 100644 index 52e2c6ca6..000000000 --- a/src/game-engine/world/actor/behaviors/melee-combat.behavior.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Actor } from '../actor'; -import { regionChangeActionFactory } from '@engine/world/action/region-change.action'; -import { Subject } from 'rxjs'; -import { logger } from '@runejs/core'; -import { Behavior, BehaviorType } from './behavior'; -import { Timestamp } from 'rxjs/dist/types/internal/types'; -import { timestamp } from 'rxjs/dist/types/operators'; -import { Player } from '../player/player'; -import { Npc } from '../npc/npc'; - -//This is exclusively for NPCs - use Auto-attack for players -export class MeleeCombatBehavior extends Behavior { - - Type = BehaviorType.Combat; - Name = 'basic-melee-combat'; - //seconds - private _CoolDown: number = 4; - private _lastAttack = new Date(); - - //this should be called when combat starts - public async init(me: Actor, them: Actor): Promise { - this.Me = me; - this.Them = them; - await super.init(me, them); - } - - public async tick() { - if (this.Me == null) return; - - return new Promise(resolve => { - if (this.Me.inCombat && this.Me.hitPoints <= 0) { - - this.Me.inCombat = false; - this.Me.isDead = true; - (this.Me as Npc).kill(false); - if (this.Them.isNpc) (this.Them as Player).playerEvents.emit('kill', this.Them); - - } - //only use boolean checks in behaviors never calculated values if you can help it (performance) - if (this.Me.inCombat) { - if (this.Distance > 5) { - this.Me.inCombat = false; - console.log('You or your target has fled from combat!'); - resolve(); - } - - //If we are not in range move there - if (this.Distance > this.Me.meleeDistance) this.Me.moveTo(this.Them); - //Are you in range to attack? - if (this.Distance <= this.Me.meleeDistance && this.coolDownElapsed) { - this.doAttack(); - this.resetCoolDown(this._CoolDown); - } - - if (!this.Me.isDead) super.tick(); - resolve(); - } - - - }); - } - public async doAttack():Promise { - return new Promise(resolve => { - //do attack stuff - this.Me.playAnimation(this.Me.getAttackAnimation()); - const _damage = this.Me.getAttackRoll(this.Them).damage; - console.log(`${(this.Me as Npc).name} attacks ${(this.Them as Player).username} for ${_damage} damage! (after the CD)`); - (this.Me as Npc).npcEvents.emit('damage', _damage); - this.Them.damage(_damage); - }); - } - public get coolDownElapsed(): boolean { - if (new Date() > this._lastAttack) return true; - return false; - } - public resetCoolDown(seconds:number):void { - this._lastAttack.setSeconds(this._lastAttack.getSeconds() + seconds); - } - - -} \ No newline at end of file diff --git a/src/game-engine/world/actor/effect.ts b/src/game-engine/world/actor/effect.ts deleted file mode 100644 index 68f33433b..000000000 --- a/src/game-engine/world/actor/effect.ts +++ /dev/null @@ -1,22 +0,0 @@ - -export abstract class Effect { - public Name: string; - public EffectType: EffectType; - public EffectId: number; - public Modifier: number =0; - -} - -export enum EffectType { - Strength, - Defense, - Attack, - Magic, - Ranged, - RecoverStats, - HPRestoreRate, - Curse, - Poison, - Fire, - EnvironmentDamage -} diff --git a/src/game-engine/world/actor/prayer.ts b/src/game-engine/world/actor/prayer.ts deleted file mode 100644 index 39895bf84..000000000 --- a/src/game-engine/world/actor/prayer.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Effect, EffectType } from './effect'; - -export class Prayer extends Effect { - AnimationId: number; - SoundId: number; - ButtonId: number; -} \ No newline at end of file diff --git a/src/game-engine/world/config/prayers.ts b/src/game-engine/world/config/prayers.ts deleted file mode 100644 index b5d7f6119..000000000 --- a/src/game-engine/world/config/prayers.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { EffectType } from '../actor/effect'; -import { Prayer } from '../actor/prayer'; -import { soundIds } from './sound-ids'; - -export const prayers: Prayer[] = [ - { - Name: 'Thick Skin', - EffectType: EffectType.Defense, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.thick_skin, - Modifier: 0.05, //ie 5% = 0.05 - ButtonId: 0 - }, - { - Name: 'Burst of Strength', - EffectType: EffectType.Strength, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.burst_of_strength, - Modifier: 0.05, //ie 5% = 0.05 - ButtonId: 1, - }, - { - Name: 'Clarity of Thought', - EffectType: EffectType.Attack, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.clarity_of_thought, - Modifier: 0.05, //ie 5% = 0.05 - ButtonId: 2 - }, - { - Name: 'Sharp Eye', - EffectType: EffectType.Ranged, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.sharp_eye, - Modifier: 0.05, //ie 5% = 0.05 - ButtonId: 36 - }, - { - Name: 'Mystic Will', - EffectType: EffectType.Magic, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.mystic_will, - Modifier: 0.05, //ie 5% = 0.05 - ButtonId: 38 - }, - { - Name: 'Rock Skin', - EffectType: EffectType.Defense, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.rock_skin, - Modifier: 0.1, //ie 5% = 0.05 - ButtonId: 3 - }, - { - Name: 'Superhuman Strength', - EffectType: EffectType.Strength, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.superhuman_strength, - Modifier: 0.1, //ie 5% = 0.05 - ButtonId: 4 - }, - { - Name: 'Improved Reflexes', - EffectType: EffectType.Attack, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.improved_reflexes, - Modifier: 0.1, //ie 5% = 0.05 - ButtonId: 5 - }, - { //This is not going to work - recover stats? what does that even mean? - Name: 'Rapid Restore', - EffectType: EffectType.RecoverStats, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.rapid_restore, - Modifier: 0.1, //ie 5% = 0.05 - ButtonId: 6 - }, - { - Name: 'Rapid Heal', - EffectType: EffectType.HPRestoreRate, - AnimationId: 645, - EffectId: 0, //graphic id - SoundId: soundIds.prayer.rapid_restore, - Modifier: 1, //ie 5% = 0.05 - ButtonId: 7 - } -]; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts deleted file mode 100644 index bcc45f6ed..000000000 --- a/src/main.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { runGameServer, world } from '@engine/game-server'; -import 'source-map-support/register'; -import { initErrorHandling } from '@engine/util/error-handling'; -import { logger } from '@runejs/core'; - - -let killed: boolean = false; - -const shutdown = (signal, cb) => { - if (killed) { - return; - } - - killed = true; - - logger.info(`[${signal}] Shutting down...`); - - world?.saveOnlinePlayers(); - - cb(); -}; - -['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT', - 'SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGTERM' -].forEach(signal => process.on(signal as any, () => { - logger.warn(`${signal} received.`); - shutdown(signal, () => process.exit(0)); -})); - -initErrorHandling(); -runGameServer(); diff --git a/src/plugins/buttons/logout-button.plugin.ts b/src/plugins/buttons/logout-button.plugin.ts index cf2808d75..6f8df8cfa 100644 --- a/src/plugins/buttons/logout-button.plugin.ts +++ b/src/plugins/buttons/logout-button.plugin.ts @@ -1,6 +1,6 @@ -import { buttonActionHandler } from '@engine/world/action/button.action'; -import { world } from '@engine/game-server'; -import { widgets } from '@engine/config'; +import { buttonActionHandler } from '@engine/action'; +import { widgets } from '@engine/config/config-handler'; +import { activeWorld } from '@engine/world'; export const handler: buttonActionHandler = (details) => { @@ -9,7 +9,7 @@ export const handler: buttonActionHandler = (details) => { player.logout(); // Update online players friends lists that have this player as a friend - const otherPlayers = world.playerList.filter(p => p && p.friendsList.indexOf(playerName) !== -1); + const otherPlayers = activeWorld.playerList.filter(p => p && p.friendsList.indexOf(playerName) !== -1); if(otherPlayers && otherPlayers.length !== 0) { otherPlayers.forEach(otherPlayer => otherPlayer.outgoingPackets.updateFriendStatus(playerName, 0)); } diff --git a/src/plugins/buttons/magic-attack.plugin.ts b/src/plugins/buttons/magic-attack.plugin.ts index e0c7a0a7c..87574f61a 100644 --- a/src/plugins/buttons/magic-attack.plugin.ts +++ b/src/plugins/buttons/magic-attack.plugin.ts @@ -1,25 +1,19 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Position } from '@engine/world/position'; -import { animationIds } from '@engine/world/config/animation-ids'; -import { soundIds } from '@engine/world/config/sound-ids'; -import { gfxIds } from '@engine/world/config/gfx-ids'; -import { loopingEvent } from '@engine/game-server'; -import { TaskExecutor } from '@engine/world/action'; -import { widgetButtonIds } from '../skills/smithing/smelting-constants'; -import { magiconnpcActionHandler, MagicOnNPCActionHook, MagicOnNPCAction } from '../../game-engine/world/action/magic-on-npc.action'; -import { logger } from '@runejs/core'; +import { Player } from '@engine/world/actor'; +import { TaskExecutor, MagicOnNPCActionHook, MagicOnNPCAction } from '@engine/action'; +import { logger } from '@runejs/common'; +import { loopingEvent } from '@engine/plugins'; const buttonIds: number[] = [ 0, // Home Teleport ]; function attack_target(player: Player, elapsedTicks: number): boolean { - logger.info('attacking?'); + logger.info('attacking?'); return true; } -const spells = ['Wind Strike','Confuse', 'Water Strike','unknown?', 'Earth Strike']; -export const activate = (task: TaskExecutor, elapsedTicks: number = 0) => { +const spells = ['Wind Strike','Confuse', 'Water Strike','unknown?', 'Earth Strike']; +export const activate = (task: TaskExecutor, elapsedTicks: number = 0) => { const { npc, player, @@ -52,5 +46,5 @@ export default { activate, interval: 0 } - } as MagicOnNPCActionHook + } as MagicOnNPCActionHook }; diff --git a/src/plugins/buttons/magic-teleports.plugin.ts b/src/plugins/buttons/magic-teleports.plugin.ts index 60af3572f..79c8ef14e 100644 --- a/src/plugins/buttons/magic-teleports.plugin.ts +++ b/src/plugins/buttons/magic-teleports.plugin.ts @@ -1,11 +1,9 @@ -import { ButtonAction, buttonActionHandler, ButtonActionHook } from '@engine/world/action/button.action'; +import { ButtonAction, ButtonActionHook, TaskExecutor } from '@engine/action'; import { Player } from '@engine/world/actor/player/player'; import { Position } from '@engine/world/position'; import { animationIds } from '@engine/world/config/animation-ids'; import { soundIds } from '@engine/world/config/sound-ids'; import { gfxIds } from '@engine/world/config/gfx-ids'; -import { loopingEvent } from '@engine/game-server'; -import { TaskExecutor } from '@engine/world/action'; enum Teleports { Home = 591, diff --git a/src/plugins/buttons/player-emotes.plugin.ts b/src/plugins/buttons/player-emotes.plugin.ts index 355c2052d..33778dfb5 100644 --- a/src/plugins/buttons/player-emotes.plugin.ts +++ b/src/plugins/buttons/player-emotes.plugin.ts @@ -1,7 +1,7 @@ -import { buttonActionHandler } from '@engine/world/action/button.action'; +import { buttonActionHandler } from '@engine/action'; import { Player } from '@engine/world/actor/player/player'; import { itemIds } from '@engine/world/config/item-ids'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; interface Emote { animationId: number; @@ -153,13 +153,18 @@ export const handler: buttonActionHandler = (details) => { const { player, buttonId } = details; const emote = emotes[buttonId]; - + if(emote.name === 'SKILLCAPE') { - if (player.getEquippedItem('back')) { - if (skillCapeEmotes.some(item => item.itemIds.includes(player.getEquippedItem('back')?.itemId))) { - const skillcapeEmote = skillCapeEmotes.filter(item => item.itemIds.includes(player.getEquippedItem('back')?.itemId)); + const equippedBackItem = player.getEquippedItem('back'); + + if (equippedBackItem) { + if (skillCapeEmotes.some(item => item.itemIds.includes(equippedBackItem.itemId))) { + const skillcapeEmote = skillCapeEmotes.filter(item => item.itemIds.includes(equippedBackItem.itemId)); player.playAnimation(skillcapeEmote[0].animationId); - player.playGraphics({ id: skillcapeEmote[0].graphicId, delay: 0, height: 0 }); + + if (skillcapeEmote[0].graphicId) { + player.playGraphics({ id: skillcapeEmote[0].graphicId, delay: 0, height: 0 }); + } } } else { player.sendMessage(`You need to be wearing a skillcape in order to perform that emote.`, true); diff --git a/src/plugins/buttons/player-setting-button.plugin.ts b/src/plugins/buttons/player-setting-button.plugin.ts index 49e2ab000..6f535cd7e 100644 --- a/src/plugins/buttons/player-setting-button.plugin.ts +++ b/src/plugins/buttons/player-setting-button.plugin.ts @@ -1,5 +1,5 @@ -import { buttonActionHandler } from '@engine/world/action/button.action'; -import { widgets } from '@engine/config'; +import { buttonActionHandler } from '@engine/action'; +import { widgets } from '@engine/config/config-handler'; const buttonIds: number[] = [ 0, // walk/run diff --git a/src/plugins/buttons/prayer.plugin.ts b/src/plugins/buttons/prayer.plugin.ts deleted file mode 100644 index 8292cfc6a..000000000 --- a/src/plugins/buttons/prayer.plugin.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Player } from '@engine/world/actor/player/player'; -import { Position } from '@engine/world/position'; -import { animationIds } from '@engine/world/config/animation-ids'; -import { soundIds } from '@engine/world/config/sound-ids'; -import { gfxIds } from '@engine/world/config/gfx-ids'; -import { loopingEvent } from '@engine/game-server'; -import { TaskExecutor } from '@engine/world/action'; -import { widgetButtonIds } from '../skills/smithing/smelting-constants'; -import { logger } from '@runejs/core'; -import { PrayerAction, PrayerActionHook } from '../../game-engine/world/action/prayer.action'; -import { widgets } from '../../game-engine/config'; -import { Prayer } from '../../game-engine/world/actor/prayer'; -import { EffectType } from '../../game-engine/world/actor/effect'; -import { prayers } from '../../game-engine/world/config/prayers'; -const buttonIds: number[] = [ - 0, // Home Teleport - 1, - 2, - 36, - 38, - 3 -]; - - -export const activate = (task: TaskExecutor, elapsedTicks: number = 0) => { - const { - player, - widgetId, - buttonId - } = task.actionData; - - prayers.filter(a => a.ButtonId == buttonId).forEach((prayer) => { - player.playAnimation(prayer.AnimationId); - player.playSound(prayer.SoundId); - player.effects.push(prayer); - }); - - console.log(`${player.username} casts ${prayers[buttonId]}`); - -}; - -export default { - pluginId: 'rs:prayer', - hooks: - { - type: 'button', - widgetId: widgets.prayerTab, - buttonIds: buttonIds, - task: { - activate, - interval: 0 - } - } as PrayerActionHook -}; diff --git a/src/plugins/combat/combat-styles.plugin.ts b/src/plugins/combat/combat-styles.plugin.ts index c3ad28d78..a4e61223a 100644 --- a/src/plugins/combat/combat-styles.plugin.ts +++ b/src/plugins/combat/combat-styles.plugin.ts @@ -1,12 +1,12 @@ -import { equipmentChangeActionHandler, EquipmentChangeAction } from '@engine/world/action/equipment-change.action'; +import { equipmentChangeActionHandler, EquipmentChangeAction } from '@engine/action/pipe/equipment-change.action'; import { ItemDetails, WeaponStyle, weaponWidgetIds } from '@engine/config/item-config'; import { widgetScripts } from '@engine/world/config/widget'; import { Player, SidebarTab } from '@engine/world/actor/player/player'; -import { findItem, widgets } from '@engine/config'; -import { buttonActionHandler } from '@engine/world/action/button.action'; +import { findItem, widgets } from '@engine/config/config-handler'; +import { buttonActionHandler } from '@engine/action/pipe/button.action'; import { combatStyles } from '@engine/world/actor/combat'; -import { serverConfig } from '@engine/game-server'; -import { playerInitActionHandler } from '@engine/world/action/player-init.action'; +import { serverConfig } from '@server/game/game-server'; +import { playerInitActionHandler } from '@engine/action/pipe/player-init.action'; export function updateCombatStyle(player: Player, weaponStyle: WeaponStyle, styleIndex: number): void { @@ -32,8 +32,8 @@ export function showUnarmed(player: Player): void { updateCombatStyle(player, 'unarmed', style); } -export function setWeaponWidget(player: Player, weaponStyle: WeaponStyle, itemDetails: ItemDetails): void { - player.modifyWidget(weaponWidgetIds[weaponStyle], { childId: 0, text: itemDetails.name || 'Unknown' }); +export function setWeaponWidget(player: Player, weaponStyle: WeaponStyle, itemDetails: ItemDetails | null): void { + player.modifyWidget(weaponWidgetIds[weaponStyle], { childId: 0, text: itemDetails?.name || 'Unknown' }); player.setSidebarWidget(SidebarTab.COMBAT, weaponWidgetIds[weaponStyle]); if(player.savedMetadata.combatStyle) { updateCombatStyle(player, weaponStyle, player.savedMetadata.combatStyle[1] || 0); @@ -77,7 +77,7 @@ const initAction: playerInitActionHandler = ({ player }) => { const combatStyleSelection: buttonActionHandler = ({ player, buttonId }) => { const equippedItem = player.getEquippedItem('main_hand'); - let weaponStyle = 'unarmed'; + let weaponStyle: string | null = 'unarmed'; if(equippedItem) { weaponStyle = findItem(equippedItem.itemId)?.equipmentData?.weaponInfo?.style || null; diff --git a/src/plugins/combat/combat.old.ts b/src/plugins/combat/combat.old.ts deleted file mode 100644 index b17ed20da..000000000 --- a/src/plugins/combat/combat.old.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { NpcInteractionAction, npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; -import { Actor } from '@engine/world/actor/actor'; -import { Player } from '@engine/world/actor/player/player'; -import { lastValueFrom, timer } from 'rxjs'; -import { World } from '@engine/world'; -import { filter, take } from 'rxjs/operators'; -import { animationIds } from '@engine/world/config/animation-ids'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { world } from '@engine/game-server'; -import { itemIds } from '@engine/world/config/item-ids'; -import { soundIds } from '@engine/world/config/sound-ids'; -import { findNpc } from '@engine/config'; -import { TaskExecutor } from '../../game-engine/world/action/hooks'; -import { wait } from '../../game-engine/world/task'; - - -class Combat { - - public readonly assailant: Actor; - public readonly victim: Actor; - public combatActive: boolean = false; - public contactInitiated: boolean = false; - - - public constructor(actor: Actor, victim: Actor) { - this.assailant = actor; - this.victim = victim; - } - - public cancelCombat(): void { - this.contactInitiated = false; - this.combatActive = false; - this.assailant.actionsCancelled.next(null); - this.victim.actionsCancelled.next(null); - } - - public async initiateCombat(): Promise { - this.combatActive = true; - await this.processAttacker(true); - - this.assailant.actionsCancelled.pipe( - filter(type => type !== 'pathing-movement'), - take(1) - ).toPromise().then(() => { - this.cancelCombat(); - }); - - this.victim.actionsCancelled.pipe( - filter(type => type !== 'pathing-movement'), - take(1) - ).toPromise().then(() => { - this.cancelCombat(); - }); - } - - public async processAttacker(firstAttack: boolean = false): Promise { - if (!this.combatActive) { - return; - } - - await this.assailant.tail(this.victim); - - if (!firstAttack) { - await lastValueFrom(timer(4 * World.TICK_LENGTH).pipe(take(1))); - } - - if (!this.combatActive) { - return; - } - - this.damage(this.assailant, this.victim); - - if (!this.contactInitiated) { - this.contactInitiated = true; - - if (this.victim instanceof Npc) { - const player = this.assailant as Player; - player.sendMessage(`Victim max health is ${this.victim.skills.hitpoints.level}.`) - } - - this.processVictim(true); - } - - this.processAttacker(); - } - - public async processVictim(firstAttack: boolean = false): Promise { - if (!this.combatActive) { - return; - } - - await this.victim.tail(this.assailant); - - if (!firstAttack) { - await timer(6 * World.TICK_LENGTH).toPromise(); - } else { - await timer(World.TICK_LENGTH).toPromise(); - } - - if (!this.combatActive) { - return; - } - - this.damage(this.victim, this.assailant); - this.processVictim(); - } - - public damage(attacker: Actor, defender: Actor): void { - const skills = attacker.skills; - const strengthBonus = (attacker instanceof Player) ? attacker.bonuses?.skill?.strength || 0 : 0; - const maxHit = this.meleeMaxHit(skills.strength.levelForExp, skills.strength.level, strengthBonus, 1); - const actualHit = Math.floor(Math.random() * (maxHit + 1)); - const attackAnim: number = attacker.getAttackAnimation(); - - // Animate attacking the opponent and play the sound of them defending - attacker.playAnimation(attackAnim); - world.playLocationSound(defender.position, defender instanceof Player ? soundIds.npc.human.playerDefence : - soundIds.npc.human.maleDefence, 5); - - const defenderState: 'alive' | 'dead' = defender.damage(actualHit); - - if (defenderState === 'dead') { - // @TODO death sounds - this.processDeath(defender, attacker); - } else { - // Play the sound of the defender being hit or blocking - world.playLocationSound(defender.position, defender instanceof Player ? soundIds.npc.human.noArmorHitPlayer : - soundIds.npc.human.noArmorHit, 5); - defender.playAnimation(defender.getBlockAnimation()); - } - } - - public async processDeath(victim: Actor, assailant?: Actor): Promise { - const deathPosition = victim.position; - - let deathAnim: number = animationIds.death; - - if (victim instanceof Npc) { - deathAnim = findNpc(victim.id)?.combatAnimations?.death || animationIds.death - } - - this.cancelCombat(); - victim.playAnimation(deathAnim); - world.playLocationSound(deathPosition, soundIds.npc.human.maleDeath, 5); - - await timer(2 * World.TICK_LENGTH).toPromise(); - - let instance = world.globalInstance; - if (victim instanceof Npc) { - victim.kill(true); - - if (assailant && assailant instanceof Player) { - instance = assailant.instance; - } - } else if (victim instanceof Player) { - // @TODO - instance = victim.instance; - } - - instance.spawnWorldItem(itemIds.bones, deathPosition, - { owner: this.assailant instanceof Player ? this.assailant : undefined, expires: 300 }); - } - - // https://forum.tip.it/topic/199687-runescape-formulas-revealed - public meleeMaxHit(strengthBase: number, strengthCurrent: number, strengthBonus: number, specialMultiplier: number): number { - const finalStrength = strengthCurrent/* + fightStyleStrengthBoost + - (strengthBase * prayerBoost) + (strengthBase * effectBoost) + - (itemSet == Dharok ? (hpBase - hpCurrent) : 0)*/; - const strengthMultiplier = (strengthBonus * 0.00175) + 0.1; - const maxHit = Math.floor((finalStrength * strengthMultiplier) + 1.05); - return Math.floor(Math.floor(Math.floor(maxHit)/* * itemSet.getMultiplier()*/) * specialMultiplier); - } - -} - -//const attackNpcAction: npcInteractionActionHandler = details => { -// const { player, npc } = details; - -// //const combatInstance = new Combat(player, npc); -// //await combatInstance.initiateCombat(); -//}; - -//export const activate = async (task: TaskExecutor, elapsedTicks: number = 0) => { -// const { player, npc, position, option } = task.actionData; - -// let completed: boolean = false; - -// console.log("starto"); -// completed = true; -// wait(100); -// if (completed) { -// task.stop(); -// } -//}; - - -//export default { -// pluginId: 'rs:combat', -// hooks: [ -// { -// type: 'npc_interaction', -// options: 'attack', -// walkTo: true, -// task: { -// activate, -// interval: 1 -// } -// } -// ] -//}; \ No newline at end of file diff --git a/src/plugins/combat/combat.plugin.ts b/src/plugins/combat/combat.plugin.ts deleted file mode 100644 index 0332a205f..000000000 --- a/src/plugins/combat/combat.plugin.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { NpcInteractionAction, npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; -import { Actor } from '@engine/world/actor/actor'; -import { Player } from '@engine/world/actor/player/player'; -import { lastValueFrom, timer } from 'rxjs'; -import { World } from '@engine/world'; -import { filter, take } from 'rxjs/operators'; -import { animationIds } from '@engine/world/config/animation-ids'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { world } from '@engine/game-server'; -import { itemIds } from '@engine/world/config/item-ids'; -import { soundIds } from '@engine/world/config/sound-ids'; -import { findNpc } from '@engine/config'; -import EventEmitter from 'events'; -import { logger } from '@runejs/core'; -import { TaskExecutor } from '../../game-engine/world/action'; -import { wait } from '../../game-engine/world/task'; -import { Behavior, BehaviorType } from '../../game-engine/world/actor/behaviors/behavior'; - - -//Kicking off combat - all subsequent action will be handed off to behaviors -export const activate = async (task: TaskExecutor, elapsedTicks: number = 0) => { - const { player, npc, position, option } = task.actionData; - - console.log(`Kicking off combat - all subsequent action will be handed off to behaviors`); - - npc.npcEvents.on('combatStart', (npc, player) => { - //this is for NPC - if it has MULTIPLE combat behaviors it will activate them all (which is the point) - npc.Behaviors.filter(a => a.Type == BehaviorType.Combat).forEach(async function (combatBehavior) { - console.log(`initting ${combatBehavior.Name}`); - await combatBehavior.init(npc, player); - npc.inCombat = true; - }); - }); - - player.playerEvents.on('combatStart', (player, npc) => { - //this is for auto attack for a player - later on if they are mind controlled or confused or even scripted this would be for that too - player.Behaviors.filter(a => a.Type == BehaviorType.Combat).forEach(async function (combatBehavior) { - console.log(`initting ${combatBehavior.Name}`); - await combatBehavior.init(player, npc); - player.inCombat = true; - }); - }) - - player.playerEvents.emit('combatStart', player, npc); - npc.npcEvents.emit('combatStart', npc, player); - await task.stop(); -}; - - - -export default { - pluginId: 'rs:combat', - hooks: [ - { - type: 'npc_interaction', - options: 'attack', - walkTo: false, - task: { - activate, - } - } - ] -}; \ No newline at end of file diff --git a/src/plugins/commands/bank-command.plugin.ts b/src/plugins/commands/bank-command.plugin.ts index 40a41183a..84a5dd3ac 100644 --- a/src/plugins/commands/bank-command.plugin.ts +++ b/src/plugins/commands/bank-command.plugin.ts @@ -1,14 +1,18 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; import { openBankInterface } from '@plugins/objects/bank/bank.plugin'; -import { getActionHooks } from '@engine/world/action/hooks'; -import { ObjectInteractionActionHook } from '@engine/world/action/object-interaction.action'; -import { advancedNumberHookFilter } from '@engine/world/action/hooks/hook-filters'; +import { getActionHooks } from '@engine/action/hook'; +import { ObjectInteractionActionHook } from '@engine/action'; +import { advancedNumberHookFilter } from '@engine/action/hook/hook-filters'; import { objectIds } from '@engine/world/config/object-ids'; const action: commandActionHandler = (details) => { const interactionActions = getActionHooks('object_interaction') .filter(plugin => advancedNumberHookFilter(plugin.objectIds, objectIds.bankBooth, plugin.options, 'use-quickly')); - interactionActions.forEach(plugin => + interactionActions.forEach(plugin => { + if (!plugin.handler) { + return; + } + plugin.handler({ player: details.player, object: { @@ -19,11 +23,12 @@ const action: commandActionHandler = (details) => { orientation: 0, type: 0 }, - objectConfig: undefined, option: 'use-quickly', position: details.player.position, - cacheOriginal: undefined - })); + objectConfig: undefined as any, + cacheOriginal: undefined as any + }) + }); }; export default { diff --git a/src/plugins/commands/camera-commands.plugin.ts b/src/plugins/commands/camera-commands.plugin.ts index b5aea8a7c..8906da711 100644 --- a/src/plugins/commands/camera-commands.plugin.ts +++ b/src/plugins/commands/camera-commands.plugin.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; import { Position } from '@engine/world/position'; diff --git a/src/plugins/commands/clear-inventory-command.plugin.ts b/src/plugins/commands/clear-inventory-command.plugin.ts index ed4dcb90e..4e7f4f4de 100644 --- a/src/plugins/commands/clear-inventory-command.plugin.ts +++ b/src/plugins/commands/clear-inventory-command.plugin.ts @@ -1,4 +1,4 @@ -import { PlayerCommandAction } from '@engine/world/action/player-command.action'; +import { PlayerCommandAction } from '@engine/action'; export default { pluginId: 'rs:clear_inventory_command', diff --git a/src/plugins/commands/client-config-command.plugin.ts b/src/plugins/commands/client-config-command.plugin.ts index 569d731f5..3c12736f8 100644 --- a/src/plugins/commands/client-config-command.plugin.ts +++ b/src/plugins/commands/client-config-command.plugin.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; const action: commandActionHandler = (details) => { const { player, args } = details; diff --git a/src/plugins/commands/current-position-command.plugin.ts b/src/plugins/commands/current-position-command.plugin.ts index f8c5f8c2d..ff8433d53 100644 --- a/src/plugins/commands/current-position-command.plugin.ts +++ b/src/plugins/commands/current-position-command.plugin.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; const action: commandActionHandler = (details) => { const { player } = details; diff --git a/src/plugins/commands/data-dump-command.plugin.ts b/src/plugins/commands/data-dump-command.plugin.ts index 0e7a4e0fd..c9cd8e6c6 100644 --- a/src/plugins/commands/data-dump-command.plugin.ts +++ b/src/plugins/commands/data-dump-command.plugin.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; import { DataDumpResult, dumpItems, dumpNpcs, dumpObjects, dumpWidgets } from '@engine/config/data-dump'; diff --git a/src/plugins/commands/give-item-command.plugin.ts b/src/plugins/commands/give-item-command.plugin.ts index 828037fb1..d65135e77 100644 --- a/src/plugins/commands/give-item-command.plugin.ts +++ b/src/plugins/commands/give-item-command.plugin.ts @@ -1,7 +1,7 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; -import { filestore } from '@engine/game-server'; +import { commandActionHandler } from '@engine/action'; +import { filestore } from '@server/game/game-server'; import { itemIds } from '@engine/world/config/item-ids'; -import { findItem, itemIdMap } from '@engine/config'; +import { findItem, itemIdMap } from '@engine/config/config-handler'; const action: commandActionHandler = (details) => { const { player, args } = details; @@ -14,7 +14,7 @@ const action: commandActionHandler = (details) => { } const itemSearch: string = args.itemSearch as string; - let itemId: number; + let itemId: number | null = null; if(itemSearch.match(/^[0-9]+$/)) { itemId = parseInt(itemSearch, 10); @@ -27,7 +27,7 @@ const action: commandActionHandler = (details) => { } } - if(isNaN(itemId)) { + if(!itemId || isNaN(itemId)) { throw new Error(`Item name not found.`); } diff --git a/src/plugins/commands/groups-debug.plugin.ts b/src/plugins/commands/groups-debug.plugin.ts new file mode 100644 index 000000000..5988c4ea3 --- /dev/null +++ b/src/plugins/commands/groups-debug.plugin.ts @@ -0,0 +1,57 @@ +import { commandActionHandler } from '@engine/action'; +import { findItemTagsInGroups, findItemTagsInGroupFilter } from '@engine/config/config-handler'; + +const selectGroups: commandActionHandler = ({ player, args, isConsole }) => { + const groups: string | number = args.groupkeys; + if(!groups || typeof groups !== 'string') { + player.sendLogMessage('invalid input', isConsole); + return; + } + player.sendLogMessage('results:', isConsole); + findItemTagsInGroups(groups.split(',')).forEach((itemName) => { + player.sendLogMessage(itemName, isConsole); + }); + return; +}; + +const filterGroups: commandActionHandler = ({ player, args, isConsole }) => { + const groups: string | number = args.groupkeys; + if(!groups || typeof groups !== 'string') { + player.sendLogMessage('invalid input', isConsole); + return; + } + + player.sendLogMessage('results:', isConsole); + findItemTagsInGroupFilter(groups.split(',')).forEach((itemName) => { + player.sendLogMessage(itemName, isConsole); + }); + return; +}; + +export default { + pluginId: 'promises:groups-debug', + hooks: [ + { + type: 'player_command', + commands: [ 'selectgroups' ], + args: [ + { + name: 'groupkeys', + type: 'string' + } + ], + handler: selectGroups + }, + { + type: 'player_command', + commands: [ 'filtergroups' ], + args: [ + { + name: 'groupkeys', + type: 'string' + } + ], + handler: filterGroups + } + ] +}; diff --git a/src/plugins/commands/pathing-commands.plugin.ts b/src/plugins/commands/pathing-commands.plugin.ts index b5cdd8830..eda0dd84f 100644 --- a/src/plugins/commands/pathing-commands.plugin.ts +++ b/src/plugins/commands/pathing-commands.plugin.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action/pipe/player-command.action'; import { Position } from '@engine/world/position'; const action: commandActionHandler = (details) => { diff --git a/src/plugins/commands/player-animation-command.plugin.ts b/src/plugins/commands/player-animation-command.plugin.ts index 749f62b18..1741fb2c4 100644 --- a/src/plugins/commands/player-animation-command.plugin.ts +++ b/src/plugins/commands/player-animation-command.plugin.ts @@ -1,6 +1,6 @@ -import { commandActionHandler, PlayerCommandAction } from '@engine/world/action/player-command.action'; +import { commandActionHandler, PlayerCommandAction } from '@engine/action'; import { Player } from '@engine/world/actor/player/player'; -import { loopingEvent } from '@engine/game-server'; +import { loopingEvent } from '@engine/plugins'; const action: commandActionHandler = (details): void => { const { player, args } = details; diff --git a/src/plugins/commands/player-graphics-command.plugin.ts b/src/plugins/commands/player-graphics-command.plugin.ts index 6d9464ea7..53b09afbc 100644 --- a/src/plugins/commands/player-graphics-command.plugin.ts +++ b/src/plugins/commands/player-graphics-command.plugin.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; const action: commandActionHandler = (details) => { const { player, args } = details; diff --git a/src/plugins/commands/quest-list-command.plugin.ts b/src/plugins/commands/quest-list-command.plugin.ts new file mode 100644 index 000000000..f172f6f43 --- /dev/null +++ b/src/plugins/commands/quest-list-command.plugin.ts @@ -0,0 +1,19 @@ +import { commandActionHandler } from '@engine/action'; +import { questMap } from '@engine/plugins'; + +const action: commandActionHandler = (details) => { + for (const quest of Object.values(questMap)) { + details.player.sendLogMessage(quest.id, details.isConsole); + } +}; + +export default { + pluginId: 'promises:quest-list-command', + hooks: [ + { + type: 'player_command', + commands: [ 'quest-list', 'quests' ], + handler: action + } + ] +}; diff --git a/src/plugins/commands/region-debug-commands.plugin.ts b/src/plugins/commands/region-debug-commands.plugin.ts index 6af129a49..60d424a61 100644 --- a/src/plugins/commands/region-debug-commands.plugin.ts +++ b/src/plugins/commands/region-debug-commands.plugin.ts @@ -1,17 +1,17 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; -import { world } from '@engine/game-server'; +import { commandActionHandler } from '@engine/action'; import { Player } from '@engine/world/actor/player/player'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; import { Position } from '@engine/world/position'; +import { activeWorld } from '@engine/world'; const debugMapRegion = (player: Player, mapRegionX: number, mapRegionY: number, worldX: number, worldY: number, level: number = -1): void => { const key = `${mapRegionX},${mapRegionY}`; - player.sendMessage(`Region ${key} - ${world.chunkManager.getRegionIdForWorldPosition(player.position)}`); + player.sendMessage(`Region ${key} - ${activeWorld.chunkManager.getRegionIdForWorldPosition(player.position)}`); - if(!world.chunkManager.regionMap.has(key)) { + if(!activeWorld.chunkManager.regionMap.has(key)) { player.sendMessage(`Map region not loaded.`); return; } @@ -20,7 +20,13 @@ const debugMapRegion = (player: Player, mapRegionX: number, mapRegionY: number, level = player.position.level; } - const region = world.chunkManager.regionMap.get(key); + const region = activeWorld.chunkManager.regionMap.get(key); + + if (!region) { + player.sendMessage(`Map region not loaded.`); + logger.error(`Map region not loaded. ${key}`) + return; + } let debug: string = `\nRegion ${key},${level}\n\n`; for(let y = 63; y >= 0; y--) { @@ -31,7 +37,7 @@ const debugMapRegion = (player: Player, mapRegionX: number, mapRegionY: number, if(tileWorldX === player.position.x && tileWorldY === player.position.y) { line[x] = '@'; } else if(region.mapFile?.tileSettings) { - const tileSettings = world.chunkManager + const tileSettings = activeWorld.chunkManager .getTile(new Position(tileWorldX, tileWorldY, level)).settings; if(!tileSettings) { @@ -61,12 +67,12 @@ const regionDebugHandler: commandActionHandler = ({ player, args }) => { }; const tileDebugHandler: commandActionHandler = ({ player }) => { - const tile = world.chunkManager.getTile(player.position); + const tile = activeWorld.chunkManager.getTile(player.position); - const tile0 = world.chunkManager.getTile(player.position.copy().setLevel(0)); - const tile1 = world.chunkManager.getTile(player.position.copy().setLevel(1)); - const tile2 = world.chunkManager.getTile(player.position.copy().setLevel(2)); - const tile3 = world.chunkManager.getTile(player.position.copy().setLevel(3)); + const tile0 = activeWorld.chunkManager.getTile(player.position.copy().setLevel(0)); + const tile1 = activeWorld.chunkManager.getTile(player.position.copy().setLevel(1)); + const tile2 = activeWorld.chunkManager.getTile(player.position.copy().setLevel(2)); + const tile3 = activeWorld.chunkManager.getTile(player.position.copy().setLevel(3)); const chunkX = player.position.chunkX + 6; const chunkY = player.position.chunkY + 6; diff --git a/src/plugins/commands/reload-content-command.plugin.ts b/src/plugins/commands/reload-content-command.plugin.ts deleted file mode 100644 index 77107fc42..000000000 --- a/src/plugins/commands/reload-content-command.plugin.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; -import { loadPlugins } from '@engine/game-server'; -import { loadPackets } from '@engine/net/inbound-packets'; -import { loadGameConfigurations } from '@engine/config'; -import { logger } from '@runejs/core'; - -const action: commandActionHandler = async (details) => { - const { player } = details; - - player.sendLogMessage(' ', details.isConsole); - player.sendLogMessage('Deleting content cache...', details.isConsole); - - // Delete node cache for all the old JS plugins - for(const path in require.cache) { - if(!path.endsWith('.js')) { - continue; - } - - const mustContain = [ - '/plugins/' - ]; - - if(path.indexOf('node_modules') !== -1) { - continue; - } - - let found = false; - for(const s of mustContain) { - if(path.indexOf(s) !== -1) { - found = true; - break; - } - } - - if(!found) { - continue; - } - - delete require.cache[path]; - } - - try { - player.sendLogMessage('Reloading plugins...', details.isConsole); - await loadPlugins(); - } catch(error) { - player.sendLogMessage('Error reloading content.', details.isConsole); - logger.error(error); - } - - try { - player.sendLogMessage('Reloading configurations...', details.isConsole); - await loadGameConfigurations(); - } catch(error) { - player.sendLogMessage('Error reloading configurations.', details.isConsole); - logger.error(error); - } - - try { - player.sendLogMessage('Reloading packets...', details.isConsole); - await loadPackets(); - } catch(error) { - player.sendLogMessage('Error reloading packets.', details.isConsole); - logger.error(error); - } - - player.sendLogMessage('Reload completed.', details.isConsole); -}; - -export default { - pluginId: 'rs:reload_content_command', - hooks: [ - { - type: 'player_command', - commands: [ - 'plugins', 'reload', 'content', 'hotload', 'refresh', 'restart', 'r' - ], - handler: action - } - ] -}; diff --git a/src/plugins/commands/reset-camera-command.plugin.ts b/src/plugins/commands/reset-camera-command.plugin.ts index 07bb8b61a..459c92d7c 100644 --- a/src/plugins/commands/reset-camera-command.plugin.ts +++ b/src/plugins/commands/reset-camera-command.plugin.ts @@ -1,4 +1,4 @@ -import { PlayerCommandAction } from '@engine/world/action/player-command.action'; +import { PlayerCommandAction } from '@engine/action'; export default { pluginId: 'rs:reset_camera_command', diff --git a/src/plugins/commands/sound-song-commands.plugin.ts b/src/plugins/commands/sound-song-commands.plugin.ts index d0525f297..2c195f958 100644 --- a/src/plugins/commands/sound-song-commands.plugin.ts +++ b/src/plugins/commands/sound-song-commands.plugin.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; const songAction: commandActionHandler = (details) => { const { player, args } = details; diff --git a/src/plugins/commands/spawn-npc-command.plugin.ts b/src/plugins/commands/spawn-npc-command.plugin.ts index fb89ae9ee..08be2ee69 100644 --- a/src/plugins/commands/spawn-npc-command.plugin.ts +++ b/src/plugins/commands/spawn-npc-command.plugin.ts @@ -1,13 +1,13 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; -import { world } from '@engine/game-server'; -import { Npc } from '@engine/world/actor/npc/npc'; -import { findNpc } from '@engine/config'; +import { commandActionHandler } from '@engine/action'; +import { Npc } from '@engine/world/actor/npc'; +import { findNpc } from '@engine/config/config-handler'; import { NpcDetails } from '@engine/config/npc-config'; import { NpcSpawn } from '@engine/config/npc-spawn-config'; +import { activeWorld } from '@engine/world'; const action: commandActionHandler = ({ player, args }) => { let npcKey: string | number = args.npcKey; - let npcDetails: NpcDetails; + let npcDetails: NpcDetails | null = null; if(typeof npcKey === 'string' && npcKey.match(/^[0-9]+$/)) { npcKey = parseInt(npcKey, 10); @@ -24,11 +24,18 @@ const action: commandActionHandler = ({ player, args }) => { npcKey = npcDetails.gameId; } + if (!npcDetails) { + player.sendMessage(`NPC ${npcKey} is not yet registered on the server.`); + return; + } + + const movementRadius: number = args.movementRadius as number; + const npc = new Npc(npcDetails ? npcDetails : npcKey, new NpcSpawn(npcDetails ? npcDetails.key : `unknown-${npcKey}`, - player.position.clone(), 0, 'WEST'), player.instance.instanceId); + player.position.clone(), movementRadius, 'WEST'), player.instance); - world.registerNpc(npc); + activeWorld.registerNpc(npc); }; export default { @@ -41,6 +48,11 @@ export default { { name: 'npcKey', type: 'either' + }, + { + name: 'movementRadius', + type: 'number', + defaultValue: 0 } ], handler: action diff --git a/src/plugins/commands/spawn-scenery-command.plugin.ts b/src/plugins/commands/spawn-scenery-command.plugin.ts index 94fc06bb4..72545cff7 100644 --- a/src/plugins/commands/spawn-scenery-command.plugin.ts +++ b/src/plugins/commands/spawn-scenery-command.plugin.ts @@ -1,8 +1,8 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; import { objectIds } from '@engine/world/config/object-ids'; import { safeDump } from 'js-yaml'; import { writeFileSync } from 'fs'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; import { LandscapeObject } from '@runejs/filestore'; const spawnSceneryAction: commandActionHandler = ({ player, args }) => { @@ -48,7 +48,7 @@ const spawnSceneryAction: commandActionHandler = ({ player, args }) => { const undoSceneryAction: commandActionHandler = (details) => { const { player } = details; - const o: LandscapeObject = player.metadata.lastSpawnedScenery; + const o = player.metadata.lastSpawnedScenery; if(!o) { return; diff --git a/src/plugins/commands/spawn-test-players-command.plugin.ts b/src/plugins/commands/spawn-test-players-command.plugin.ts index 0b8828777..aba8468c1 100644 --- a/src/plugins/commands/spawn-test-players-command.plugin.ts +++ b/src/plugins/commands/spawn-test-players-command.plugin.ts @@ -1,8 +1,9 @@ import { Position } from '@engine/world/position'; import { Player } from '@engine/world/actor/player/player'; -import { world } from '@engine/game-server'; import { World } from '@engine/world'; -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; +import { activeWorld } from '@engine/world'; +import { Isaac } from '@engine/net'; const handler: commandActionHandler = ({ player, args }) => { @@ -18,9 +19,9 @@ const handler: commandActionHandler = ({ player, args }) => { let xOffset: number = 0; let yOffset: number = 0; - const spawnChunk = world.chunkManager.getChunkForWorldPosition(new Position(x, y, 0)); + const spawnChunk = activeWorld.chunkManager.getChunkForWorldPosition(new Position(x, y, 0)); - const worldSlotsRemaining = world.playerSlotsRemaining() - 1; + const worldSlotsRemaining = activeWorld.playerSlotsRemaining() - 1; if(worldSlotsRemaining <= 0) { player.sendMessage(`Error: The game world is full.`); return; @@ -32,10 +33,12 @@ const handler: commandActionHandler = ({ player, args }) => { player.sendMessage(`Warning: There was only room for ${playerSpawnCount}/${playerCount} player spawns.`); } + // TODO (JameskmongeR) what's the difference between this and `generateFakePlayers` + for(let i = 0; i < playerSpawnCount; i++) { - const testPlayer = new Player(null, null, null, i, - `test${i}`, 'abs', true); - world.registerPlayer(testPlayer); + // TODO (Jameskmonger) we should be able to create a player without a connection, and without passing nulls in + const testPlayer = new Player(null as any, null as any, null as any, i, `test${i}`, 'abs', true); + activeWorld.registerPlayer(testPlayer); testPlayer.interfaceState.closeAllSlots(); xOffset++; @@ -46,7 +49,7 @@ const handler: commandActionHandler = ({ player, args }) => { } testPlayer.position = new Position(x + xOffset, y + yOffset, 0); - const newChunk = world.chunkManager.getChunkForWorldPosition(testPlayer.position); + const newChunk = activeWorld.chunkManager.getChunkForWorldPosition(testPlayer.position); if(!spawnChunk.equals(newChunk)) { spawnChunk.removePlayer(testPlayer); diff --git a/src/plugins/commands/stat-commands.plugin.ts b/src/plugins/commands/stat-commands.plugin.ts index ff8039732..37274a846 100644 --- a/src/plugins/commands/stat-commands.plugin.ts +++ b/src/plugins/commands/stat-commands.plugin.ts @@ -1,9 +1,9 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; const setLevelAction: commandActionHandler = ({ player, args }) => { const skillId = args?.skillId || null; - const level: number = args?.level as number || null; + const level: number | null = args?.level as number || null; if(!skillId || !level) { player.sendMessage(`Invalid syntax: Use ::setlevel skill_id skill_level`); diff --git a/src/plugins/commands/teleport-command.plugin.ts b/src/plugins/commands/teleport-command.plugin.ts index 60a370ac8..e6f701941 100644 --- a/src/plugins/commands/teleport-command.plugin.ts +++ b/src/plugins/commands/teleport-command.plugin.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; import { Position } from '@engine/world/position'; const action: commandActionHandler = (details) => { diff --git a/src/plugins/commands/transform-command.plugin.js b/src/plugins/commands/transform-command.plugin.js deleted file mode 100644 index abb86fe33..000000000 --- a/src/plugins/commands/transform-command.plugin.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - pluginId: 'rs:transform_command', - hooks: [ - { - type: 'player_command', - commands: 'transform', - args: [ { - name: 'npcKey', - type: 'either', - defaultValue: null - } ], - handler: details => details.player.transformInto(details && details.args ? details.args['npcKey'] : null) - } - ] -}; diff --git a/src/plugins/commands/transform-command.plugin.ts b/src/plugins/commands/transform-command.plugin.ts new file mode 100644 index 000000000..275f0b9ed --- /dev/null +++ b/src/plugins/commands/transform-command.plugin.ts @@ -0,0 +1,25 @@ +import { commandActionHandler, PlayerCommandActionHook } from '@engine/action'; + +const action: commandActionHandler = (details) => { + const { player, args } = details; + + player.transformInto(details && details.args ? details.args['npcKey'] : null) +}; + +export default { + pluginId: 'rs:transform_command', + hooks: [ + { + type: 'player_command', + commands: [ 'transform' ], + args: [ + { + name: 'npcKey', + type: 'either', + defaultValue: undefined + } + ], + handler: action + } as PlayerCommandActionHook + ] +}; diff --git a/src/plugins/commands/travel-back-command.plugin.ts b/src/plugins/commands/travel-back-command.plugin.ts index 63dbea9cf..b11e20674 100644 --- a/src/plugins/commands/travel-back-command.plugin.ts +++ b/src/plugins/commands/travel-back-command.plugin.ts @@ -1,11 +1,11 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; import { Skill } from '@engine/world/actor/skills'; const action: commandActionHandler = (details) => { const { player } = details; - if (player.metadata['lastPosition']) { - player.teleport(player.metadata['lastPosition']); + if (player.metadata.lastPosition) { + player.teleport(player.metadata.lastPosition); } }; diff --git a/src/plugins/commands/travel-command.plugin.ts b/src/plugins/commands/travel-command.plugin.ts index db42af597..20efdf0e2 100644 --- a/src/plugins/commands/travel-command.plugin.ts +++ b/src/plugins/commands/travel-command.plugin.ts @@ -1,12 +1,12 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; -import { world } from '@engine/game-server'; +import { commandActionHandler } from '@engine/action'; import { TravelLocation } from '@engine/world/config/travel-locations'; +import { activeWorld } from '@engine/world'; const action: commandActionHandler = (details) => { const { player, args } = details; const search: string = args.search as string; - const location = world.travelLocations.find(search) as TravelLocation; + const location = activeWorld.travelLocations.find(search) as TravelLocation; if (location) { player.teleport(location.position); diff --git a/src/plugins/commands/widget-commands.plugin.ts b/src/plugins/commands/widget-commands.plugin.ts index 8eef437ac..69b419830 100644 --- a/src/plugins/commands/widget-commands.plugin.ts +++ b/src/plugins/commands/widget-commands.plugin.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; const action: commandActionHandler = (details) => { const { player, args } = details; diff --git a/src/plugins/dialogue/dialogue-option.plugin.ts b/src/plugins/dialogue/dialogue-option.plugin.ts index 4fe989d1c..60aa49a07 100644 --- a/src/plugins/dialogue/dialogue-option.plugin.ts +++ b/src/plugins/dialogue/dialogue-option.plugin.ts @@ -1,4 +1,4 @@ -import { widgetInteractionActionHandler } from '@engine/world/action/widget-interaction.action'; +import { widgetInteractionActionHandler } from '@engine/action'; const dialogueIds = [ 64, 65, 66, 67, 241, diff --git a/src/plugins/dialogue/item-selection.plugin.ts b/src/plugins/dialogue/item-selection.plugin.ts index 9c7d81933..4fb41200b 100644 --- a/src/plugins/dialogue/item-selection.plugin.ts +++ b/src/plugins/dialogue/item-selection.plugin.ts @@ -1,4 +1,4 @@ -import { widgetInteractionActionHandler } from '@engine/world/action/widget-interaction.action'; +import { widgetInteractionActionHandler } from '@engine/action'; /** * Handles an item selection dialogue choice. diff --git a/src/plugins/items/buckets/empty-container.plugin.ts b/src/plugins/items/buckets/empty-container.plugin.ts index 12ca0ccff..8e2c801d8 100644 --- a/src/plugins/items/buckets/empty-container.plugin.ts +++ b/src/plugins/items/buckets/empty-container.plugin.ts @@ -1,8 +1,8 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; import { soundIds } from '@engine/world/config/sound-ids'; import { itemIds } from '@engine/world/config/item-ids'; import { getItemFromContainer } from '@engine/world/items/item-container'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; export const handler: itemInteractionActionHandler = (details) => { const { player, itemId, itemSlot } = details; diff --git a/src/plugins/items/buckets/fill-container.plugin.ts b/src/plugins/items/buckets/fill-container.plugin.ts index d3c2dfaa8..970310380 100644 --- a/src/plugins/items/buckets/fill-container.plugin.ts +++ b/src/plugins/items/buckets/fill-container.plugin.ts @@ -1,9 +1,10 @@ -import { itemOnObjectActionHandler } from '@engine/world/action/item-on-object.action'; -import { filestore } from '@engine/game-server'; +import { itemOnObjectActionHandler } from '@engine/action'; +import { filestore } from '@server/game/game-server'; import { itemIds } from '@engine/world/config/item-ids'; import { animationIds } from '@engine/world/config/animation-ids'; import { soundIds } from '@engine/world/config/sound-ids'; -import { findItem } from '@engine/config'; +import { findItem } from '@engine/config/config-handler'; +import { logger } from '@runejs/common'; const FountainIds: number[] = [879]; @@ -12,6 +13,12 @@ const WellIds: number[] = [878]; export const handler: itemOnObjectActionHandler = (details) => { const { player, objectConfig, item } = details; const itemDef = findItem(item.itemId); + + if (!itemDef) { + logger.error(`No item found for fill container plugin: ${item.itemId}`); + return; + } + if (item.itemId !== itemIds.bucket && WellIds.indexOf(objectConfig.gameId) > -1) { player.sendMessage(`If I drop my ${itemDef.name.toLowerCase()} down there, I don't think I'm likely to get it back.`); return; @@ -27,11 +34,15 @@ export const handler: itemOnObjectActionHandler = (details) => { case itemIds.jug: player.giveItem(itemIds.jugOfWater); break; + } + const objectName = details.objectConfig.name || ''; + if (!objectName) { + logger.warn(`Fill container object ${details.object.objectId} has no name.`); } - player.sendMessage(`You fill the ${itemDef.name.toLowerCase()} from the ${objectConfig.name.toLowerCase()}.`); + player.sendMessage(`You fill the ${itemDef.name.toLowerCase()} from the ${objectName.toLowerCase()}.`); }; diff --git a/src/plugins/items/capes/skillcape-emotes.plugin.ts b/src/plugins/items/capes/skillcape-emotes.plugin.ts index 6725995e1..99ad80cc4 100644 --- a/src/plugins/items/capes/skillcape-emotes.plugin.ts +++ b/src/plugins/items/capes/skillcape-emotes.plugin.ts @@ -1,5 +1,5 @@ import { lockEmote, unlockEmote } from '@plugins/buttons/player-emotes.plugin'; -import { equipmentChangeActionHandler } from '@engine/world/action/equipment-change.action'; +import { equipmentChangeActionHandler } from '@engine/action'; import { itemIds } from '@engine/world/config/item-ids'; export const skillcapeIds: Array = Object.keys( diff --git a/src/plugins/items/consumables/eating.plugin.ts b/src/plugins/items/consumables/eating.plugin.ts index af17f907d..6bd9ad2c7 100644 --- a/src/plugins/items/consumables/eating.plugin.ts +++ b/src/plugins/items/consumables/eating.plugin.ts @@ -1,10 +1,11 @@ -import { findItem, widgets } from '@engine/config'; +import { findItem, widgets } from '@engine/config/config-handler'; import { SkillName } from '@engine/world/actor/skills'; import { animationIds } from '@engine/world/config/animation-ids'; import { soundIds } from '@engine/world/config/sound-ids'; import { randomBetween } from '@engine/util/num'; import { World } from '@engine/world'; -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; +import { logger } from '@runejs/common'; export const action: itemInteractionActionHandler = (details) => { @@ -31,12 +32,18 @@ export const action: itemInteractionActionHandler = (details) => { return; } - if(player.inventory.items[itemSlot].itemId !== itemId){ + const inventoryItem = player.inventory.items[itemSlot]; + + if(!inventoryItem || inventoryItem.itemId !== itemId){ return; } - if(itemDetails.metadata.consume_effects.replaced_by) { - player.inventory.items[itemSlot] = { itemId: findItem(itemDetails.metadata.consume_effects.replaced_by)?.gameId, amount: 1 }; + const replacementItemDetails = itemDetails.metadata.consume_effects.replaced_by + ? findItem(itemDetails.metadata.consume_effects.replaced_by) + : null; + + if(replacementItemDetails) { + player.inventory.items[itemSlot] = { itemId: replacementItemDetails.gameId, amount: 1 }; } else { player.inventory.items[itemSlot] = null; } diff --git a/src/plugins/items/drop-item.plugin.ts b/src/plugins/items/drop-item.plugin.ts index 9f4785bd6..798bfb360 100644 --- a/src/plugins/items/drop-item.plugin.ts +++ b/src/plugins/items/drop-item.plugin.ts @@ -1,9 +1,9 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { ActionCancelType, itemInteractionActionHandler } from '@engine/action'; import { soundIds } from '@engine/world/config/sound-ids'; import { getItemFromContainer } from '@engine/world/items/item-container'; -import { serverConfig } from '@engine/game-server'; +import { serverConfig } from '@server/game/game-server'; import { Rights } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; import { dialogue, execute } from '@engine/world/actor/dialogue'; @@ -43,7 +43,8 @@ export const handler: itemInteractionActionHandler = ({ player, itemId, itemSlot player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, itemSlot, null); player.playSound(soundIds.dropItem, 5); player.instance.spawnWorldItem(item, player.position, { owner: player, expires: 300 }); - player.actionsCancelled.next(null); + // (Jameskmonger) actionsCancelled is deprecated, casting this to satisfy the typecheck for now + player.actionsCancelled.next(null as unknown as ActionCancelType); }; export default { diff --git a/src/plugins/items/equipment/equip-item.plugin.ts b/src/plugins/items/equipment/equip-item.plugin.ts index 44f180f3b..11d619e17 100644 --- a/src/plugins/items/equipment/equip-item.plugin.ts +++ b/src/plugins/items/equipment/equip-item.plugin.ts @@ -1,5 +1,5 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; -import { widgets } from '@engine/config'; +import { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; +import { widgets } from '@engine/config/config-handler'; export const handler: itemInteractionActionHandler = (details) => { const { player, itemId, itemSlot, itemDetails } = details; diff --git a/src/plugins/items/equipment/equipment-stats.plugin.ts b/src/plugins/items/equipment/equipment-stats.plugin.ts index 15fa5c4de..5d16f04a2 100644 --- a/src/plugins/items/equipment/equipment-stats.plugin.ts +++ b/src/plugins/items/equipment/equipment-stats.plugin.ts @@ -1,31 +1,12 @@ -import { buttonActionHandler } from '@engine/world/action/button.action'; +import { buttonActionHandler } from '@engine/action'; import { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config'; - -export function updateBonusStrings(player: Player): void { - [ - { id: 108, text: 'Stab', value: player.bonuses.offensive.stab }, - { id: 109, text: 'Slash', value: player.bonuses.offensive.slash }, - { id: 110, text: 'Crush', value: player.bonuses.offensive.crush }, - { id: 111, text: 'Magic', value: player.bonuses.offensive.magic }, - { id: 112, text: 'Range', value: player.bonuses.offensive.ranged }, - { id: 113, text: 'Stab', value: player.bonuses.defensive.stab }, - { id: 114, text: 'Slash', value: player.bonuses.defensive.slash }, - { id: 115, text: 'Crush', value: player.bonuses.defensive.crush }, - { id: 116, text: 'Magic', value: player.bonuses.defensive.magic }, - { id: 117, text: 'Range', value: player.bonuses.defensive.ranged }, - { id: 119, text: 'Strength', value: player.bonuses.skill.strength }, - { id: 120, text: 'Prayer', value: player.bonuses.skill.prayer }, - ].forEach(bonus => player.modifyWidget(widgets.equipmentStats.widgetId, { childId: bonus.id, - text: `${bonus.text}: ${bonus.value > 0 ? `+${bonus.value}` : bonus.value}` })); -} +import { widgets } from '@engine/config/config-handler'; export const handler: buttonActionHandler = (details) => { const { player } = details; player.updateBonuses(); - - updateBonusStrings(player); + player.syncBonuses(); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.equipmentStats, player.equipment); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); diff --git a/src/plugins/items/equipment/unequip-item.plugin.ts b/src/plugins/items/equipment/unequip-item.plugin.ts index ccea61e5d..30df2f5fb 100644 --- a/src/plugins/items/equipment/unequip-item.plugin.ts +++ b/src/plugins/items/equipment/unequip-item.plugin.ts @@ -1,6 +1,6 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; import { getItemFromContainer } from '@engine/world/items/item-container'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; export const handler: itemInteractionActionHandler = (details) => { const { player, itemId, itemSlot, itemDetails } = details; diff --git a/src/plugins/items/herblore/clean-herb.ts b/src/plugins/items/herblore/clean-herb.ts index 9fc1764d8..9c7dcbe30 100644 --- a/src/plugins/items/herblore/clean-herb.ts +++ b/src/plugins/items/herblore/clean-herb.ts @@ -1,7 +1,8 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; -import { findItem, widgets } from '@engine/config'; +import { itemInteractionActionHandler } from '@engine/action'; +import { findItem, widgets } from '@engine/config/config-handler'; import { soundIds } from '@engine/world/config/sound-ids'; import { ItemDetails } from '@engine/config/item-config'; +import { logger } from '@runejs/common'; interface IGrimyHerb { grimy: ItemDetails; @@ -9,97 +10,105 @@ interface IGrimyHerb { level: number; experience: number; } + +/** + * A list of all the herbs that can be cleaned. + * + * (Jameskmonger) I have put ! after findItem() because we know the items exist. + */ const herbs: IGrimyHerb[] = [ + /* eslint-disable @typescript-eslint/no-non-null-assertion */ { - grimy: findItem('rs:grimy_guam'), - clean: findItem('rs:herb_guam'), + grimy: findItem('rs:grimy_guam')!, + clean: findItem('rs:herb_guam')!, level: 3, experience: 2.5 }, { - grimy: findItem('rs:grimy_marrentill'), - clean: findItem('rs:herb_marrentill'), + grimy: findItem('rs:grimy_marrentill')!, + clean: findItem('rs:herb_marrentill')!, level: 5, experience: 3.8 }, { - grimy: findItem('rs:grimy_tarromin'), - clean: findItem('rs:herb_tarromin'), + grimy: findItem('rs:grimy_tarromin')!, + clean: findItem('rs:herb_tarromin')!, level: 11, experience: 5 }, { - grimy: findItem('rs:grimy_harralander'), - clean: findItem('rs:herb_harralander'), + grimy: findItem('rs:grimy_harralander')!, + clean: findItem('rs:herb_harralander')!, level: 20, experience: 6.3 }, { - grimy: findItem('rs:grimy_ranarr'), - clean: findItem('rs:herb_ranarr'), + grimy: findItem('rs:grimy_ranarr')!, + clean: findItem('rs:herb_ranarr')!, level: 25, experience: 7.5 }, { - grimy: findItem('rs:grimy_toadflax'), - clean: findItem('rs:herb_toadflax'), + grimy: findItem('rs:grimy_toadflax')!, + clean: findItem('rs:herb_toadflax')!, level: 30, experience: 8 }, { - grimy: findItem('rs:grimy_irit'), - clean: findItem('rs:herb_irit'), + grimy: findItem('rs:grimy_irit')!, + clean: findItem('rs:herb_irit')!, level: 40, experience: 8.8 }, { - grimy: findItem('rs:grimy_avantoe'), - clean: findItem('rs:herb_avantoe'), + grimy: findItem('rs:grimy_avantoe')!, + clean: findItem('rs:herb_avantoe')!, level: 48, experience: 10 }, { - grimy: findItem('rs:grimy_kwuarm'), - clean: findItem('rs:herb_kwuarm'), + grimy: findItem('rs:grimy_kwuarm')!, + clean: findItem('rs:herb_kwuarm')!, level: 54, experience: 11.3 }, { - grimy: findItem('rs:grimy_snapdragon'), - clean: findItem('rs:herb_snapdragon'), + grimy: findItem('rs:grimy_snapdragon')!, + clean: findItem('rs:herb_snapdragon')!, level: 59, experience: 11.8 }, { - grimy: findItem('rs:grimy_cadantine'), - clean: findItem('rs:herb_cadantine'), + grimy: findItem('rs:grimy_cadantine')!, + clean: findItem('rs:herb_cadantine')!, level: 65, experience: 12.5 }, { - grimy: findItem('rs:grimy_lantadyme'), - clean: findItem('rs:herb_lantadyme'), + grimy: findItem('rs:grimy_lantadyme')!, + clean: findItem('rs:herb_lantadyme')!, level: 67, experience: 13.1 }, { - grimy: findItem('rs:grimy_dwarf_weed'), - clean: findItem('rs:herb_dwarf_weed'), + grimy: findItem('rs:grimy_dwarf_weed')!, + clean: findItem('rs:herb_dwarf_weed')!, level: 70, experience: 13.8 }, { - grimy: findItem('rs:grimy_torstol'), - clean: findItem('rs:herb_torstol'), + grimy: findItem('rs:grimy_torstol')!, + clean: findItem('rs:herb_torstol')!, level: 75, experience: 15 }, + /* eslint-enable @typescript-eslint/no-non-null-assertion */ ] export const action: itemInteractionActionHandler = details => { const { player, itemId, itemSlot } = details; - const herb: IGrimyHerb = herbs.find((herb) => herb.grimy.gameId === itemId); + const herb = herbs.find((herb) => herb.grimy.gameId === itemId); if(!herb) { return; } @@ -107,10 +116,20 @@ export const action: itemInteractionActionHandler = details => { player.sendMessage(`You need a Herblore level of ${herb.level} to identify this herb.`, true); return; } + + const inventoryItem = player.inventory.items[itemSlot]; + // Always check for cheaters - if(!player.inventory.items[itemSlot] && player.inventory.items[itemSlot].itemId === herb.grimy.gameId) { + if (!inventoryItem) { + logger.warn(`[herblore] Player ${player.username} tried to clean herb without having it in their inventory.`); return; } + + if (inventoryItem.itemId !== herb.grimy.gameId) { + logger.warn(`[herblore] Player ${player.username} tried to clean herb but itemId did not match.`); + return; + } + player.skills.addExp('herblore', herb.experience); player.inventory.set(itemSlot, { itemId: herb.clean.gameId, amount: 1 }); details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, details.player.inventory); diff --git a/src/plugins/items/move-item.plugin.ts b/src/plugins/items/move-item.plugin.ts index f72887079..7da6c37d0 100644 --- a/src/plugins/items/move-item.plugin.ts +++ b/src/plugins/items/move-item.plugin.ts @@ -1,7 +1,7 @@ -import { itemSwapActionHandler } from '@engine/world/action/item-swap.action'; +import { itemSwapActionHandler } from '@engine/action'; import { ItemContainer } from '@engine/world/items/item-container'; import { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; type WidgetDetail = [ number, number, (player: Player) => ItemContainer ]; diff --git a/src/plugins/items/pickup-item.plugin.ts b/src/plugins/items/pickup-item.plugin.ts index 4fee07ad0..d3224b208 100644 --- a/src/plugins/items/pickup-item.plugin.ts +++ b/src/plugins/items/pickup-item.plugin.ts @@ -1,7 +1,8 @@ -import { spawnedItemInteractionHandler } from '@engine/world/action/spawned-item-interaction.action'; +import { ActionCancelType, spawnedItemInteractionHandler } from '@engine/action'; import { Item } from '@engine/world/items/item'; import { soundIds } from '@engine/world/config/sound-ids'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; +import { logger } from '@runejs/common'; export const handler: spawnedItemInteractionHandler = ({ player, worldItem, itemDetails }) => { @@ -13,7 +14,7 @@ export const handler: spawnedItemInteractionHandler = ({ player, worldItem, item const existingItemIndex = inventory.findIndex(worldItem.itemId); if(existingItemIndex !== -1) { const existingItem = inventory.items[existingItemIndex]; - if(existingItem.amount + worldItem.amount >= 2147483647) { + if(existingItem && (existingItem.amount + worldItem.amount >= 2147483647)) { // @TODO create new item stack return; } else { @@ -31,6 +32,11 @@ export const handler: spawnedItemInteractionHandler = ({ player, worldItem, item return; } + if (!worldItem.instance) { + logger.error(`World item ${worldItem.itemId} has no instance`); + return; + } + worldItem.instance.despawnWorldItem(worldItem); const item: Item = { @@ -39,9 +45,16 @@ export const handler: spawnedItemInteractionHandler = ({ player, worldItem, item }; const addedItem = inventory.add(item); + + if (!addedItem) { + logger.error(`Failed to add item ${item.itemId} to inventory for player ${player.username}`); + return; + } + player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, addedItem.slot, addedItem.item); player.playSound(soundIds.pickupItem, 3); - player.actionsCancelled.next(null); + // (Jameskmonger) actionsCancelled is deprecated, casting this to satisfy the typecheck for now + player.actionsCancelled.next(null as unknown as ActionCancelType); }; export default { diff --git a/src/plugins/items/pots/empty-pot.plugin.ts b/src/plugins/items/pots/empty-pot.plugin.ts index ea9e9f080..534773654 100644 --- a/src/plugins/items/pots/empty-pot.plugin.ts +++ b/src/plugins/items/pots/empty-pot.plugin.ts @@ -1,8 +1,8 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; import { soundIds } from '@engine/world/config/sound-ids'; import { itemIds } from '@engine/world/config/item-ids'; import { getItemFromContainer } from '@engine/world/items/item-container'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; export const action: itemInteractionActionHandler = (details) => { const { player, itemId, itemSlot } = details; diff --git a/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts b/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts index 36a54a14c..d6fb43557 100644 --- a/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts +++ b/src/plugins/items/rotten-potato/helpers/rotten-potato-helpers.ts @@ -1,10 +1,16 @@ -import { findItem, widgets } from '@engine/config'; +import { findItem, widgets } from '@engine/config/config-handler'; import { ItemDetails } from '@engine/config/item-config'; import { Rights } from '@engine/world/actor/player/player'; -import { ItemOnItemAction } from '@engine/world/action/item-on-item.action'; -import { WidgetInteractionAction } from '@engine/world/action/widget-interaction.action'; +import { ItemOnItemAction } from '@engine/action/pipe/item-on-item.action'; +import { WidgetInteractionAction } from '@engine/action/pipe/widget-interaction.action'; -export const RottenPotatoItem: ItemDetails = findItem('rs:rotten_potato'); +/** + * The rotten potato item. + * + * (Jameskmonger) I have put ! after findItem() because we know the item exists. + */ +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion +export const RottenPotatoItem: ItemDetails = findItem('rs:rotten_potato')!; export const ExecuteIfAdmin = (details: ItemOnItemAction | WidgetInteractionAction, callback) => { diff --git a/src/plugins/items/rotten-potato/helpers/rotten-potato-travel.ts b/src/plugins/items/rotten-potato/helpers/rotten-potato-travel.ts index 7685f08c9..f4ea03ace 100644 --- a/src/plugins/items/rotten-potato/helpers/rotten-potato-travel.ts +++ b/src/plugins/items/rotten-potato/helpers/rotten-potato-travel.ts @@ -1,8 +1,8 @@ import { Player } from '@engine/world/actor/player/player'; -import { world } from '@engine/game-server'; import { widgetInteractionActionHandler -} from '@engine/world/action/widget-interaction.action'; +} from '@engine/action'; +import { activeWorld } from '@engine/world'; export function openTravel(player: Player, page: number) { const widget = player.interfaceState.openWidget(27, { @@ -19,7 +19,7 @@ export function openTravel(player: Player, page: number) { player.modifyWidget(widget.widgetId, { childId: 97, - hidden: Math.round(world.travelLocations.locations.length / 30) === page + hidden: Math.round(activeWorld.travelLocations.locations.length / 30) === page }) player.modifyWidget(widget.widgetId, { @@ -41,20 +41,20 @@ export function openTravel(player: Player, page: number) { for (let i = 0; i < 30; i+=2) { player.modifyWidget(widget.widgetId, { childId: 101+i, - text: world.travelLocations.locations[currentLocation]?.name || '', - hidden: !world.travelLocations.locations[currentLocation]?.name + text: activeWorld.travelLocations.locations[currentLocation]?.name || '', + hidden: !activeWorld.travelLocations.locations[currentLocation]?.name }) currentLocation++; } for (let i = 0; i < 30; i+=2) { player.modifyWidget(widget.widgetId, { childId: 131+i-1, - hidden: !world.travelLocations.locations[currentLocation]?.name + hidden: !activeWorld.travelLocations.locations[currentLocation]?.name }) player.modifyWidget(widget.widgetId, { childId: 131+i, - text: world.travelLocations.locations[currentLocation]?.name || '', - hidden: !world.travelLocations.locations[currentLocation]?.name + text: activeWorld.travelLocations.locations[currentLocation]?.name || '', + hidden: !activeWorld.travelLocations.locations[currentLocation]?.name }) currentLocation++; } @@ -78,7 +78,7 @@ export const travelMenuInteract: widgetInteractionActionHandler = (details) => { openTravel(details.player, playerWidget.metadata.page+1) return; } - let selectedIndex = undefined; + let selectedIndex: number | undefined = undefined; if(details.childId >= 101 && details.childId <= 129) { selectedIndex = (details.childId - 99)/2 - 1; } @@ -86,7 +86,7 @@ export const travelMenuInteract: widgetInteractionActionHandler = (details) => { selectedIndex = ((details.childId - 129)/2 -1) + 15; } if(selectedIndex != undefined) { - details.player.teleport(world.travelLocations.locations[selectedIndex + (30 * (playerWidget.metadata.page-1))].position) + details.player.teleport(activeWorld.travelLocations.locations[selectedIndex + (30 * (playerWidget.metadata.page-1))].position) details.player.interfaceState.closeAllSlots() } else { openTravel(details.player, playerWidget.metadata.page) diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-command-hook.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-command-hook.ts index c4e4c4fd8..5ddf4e97d 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-command-hook.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-command-hook.ts @@ -1,4 +1,4 @@ -import { commandActionHandler } from '@engine/world/action/player-command.action'; +import { commandActionHandler } from '@engine/action'; const spawnPotato: commandActionHandler = (details) => { diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts index 9bcce5dcc..9878949d8 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-eat.ts @@ -1,4 +1,4 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; import { dialogue, execute } from '@engine/world/actor/dialogue'; enum DialogueOption { @@ -32,7 +32,9 @@ const eatPotato: itemInteractionActionHandler = async (details) => { ], ] ]); - switch (chosenOption) { + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + switch (chosenOption!) { case DialogueOption.SET_ALL_STATS: break; case DialogueOption.TELEPORT_TO_PLAYER: diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-item.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-item.ts index 2a03b4aa2..7e97faf70 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-item.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-item.ts @@ -1,13 +1,21 @@ -import { itemOnItemActionHandler } from '@engine/world/action/item-on-item.action'; +import { itemOnItemActionHandler } from '@engine/action'; import { RottenPotatoItem } from '@plugins/items/rotten-potato/helpers/rotten-potato-helpers'; -import { findItem } from '@engine/config'; +import { findItem } from '@engine/config/config-handler'; const itemOnPotato: itemOnItemActionHandler = (details) => { const slotToDelete = details.usedItem.itemId === RottenPotatoItem.gameId ? details.usedWithSlot : details.usedSlot; - const item = details.player.inventory.items[slotToDelete].itemId; + + const inventoryItem = details.player.inventory.items[slotToDelete]; + + if (!inventoryItem) { + details.player.sendMessage(`You don't have that item in your inventory.`); + return; + } + + const item = inventoryItem.itemId; const itemDetails = findItem(item); details.player.removeItem(slotToDelete); - details.player.sendLogMessage(`Whee... ${itemDetails.name} All gone!`, false) + details.player.sendLogMessage(`Whee... ${itemDetails?.name || 'Unknown item'} All gone!`, false) }; export default itemOnPotato; diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-player.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-player.ts index ff609a1b8..427babcbe 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-player.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-item-on-player.ts @@ -1,8 +1,9 @@ -import { widgets } from '@engine/config'; -import { itemOnPlayerActionHandler } from '@engine/world/action/item-on-player.action'; -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { widgets } from '@engine/config/config-handler'; +import { itemOnPlayerActionHandler } from '@engine/action'; +import { itemInteractionActionHandler } from '@engine/action'; import { Item } from '@engine/world/items/item'; -import { ItemContainer } from '@engine/world/items/item-container'; +import { Player } from '@engine/world/actor'; +import { logger } from '@runejs/common'; export const potatoOnPlayer: itemOnPlayerActionHandler = (details) => { const widget = details.player.interfaceState.openWidget(widgets.bank.depositBoxWidget.widgetId, { @@ -27,7 +28,7 @@ export const potatoManipulatePlayerInventory: itemInteractionActionHandler = (de if(!playerWidget) { return; } - const otherPlayer = playerWidget.metadata['player']; + const otherPlayer: Player = playerWidget.metadata['player']; if(!otherPlayer) { return; @@ -44,29 +45,44 @@ export const potatoManipulatePlayerInventory: itemInteractionActionHandler = (de countToRemove = +details.option.replace('deposit-', ''); } + const slotsWithItem = otherPlayer.inventory.findAll(details.itemId); + let itemAmount = 0; + slotsWithItem.forEach((slot) => { + const item = otherPlayer.inventory.items[slot]; - const otherPlayerInventory: ItemContainer = otherPlayer.inventory; - const playerInventory: ItemContainer = details.player.inventory; - const slotsWithItem: number[] = otherPlayerInventory.findAll(details.itemId); - let itemAmount: number = 0; - slotsWithItem.forEach((slot) => itemAmount += otherPlayerInventory.items[slot].amount); + if (!item) { + throw new Error(`Container item was not present, for item id ${details.itemId} in inventory, while trying to deposit`); + } + + if (item.itemId !== details.itemId) { + throw new Error(`Container item id mismatch, for item id ${details.itemId} in inventory, while trying to deposit`); + } + + itemAmount += item.amount; + }); if (countToRemove == -1 || countToRemove > itemAmount) { countToRemove = itemAmount; } - if (!playerInventory.canFit({ itemId: itemIdToAdd, amount: countToRemove })) { + if (!details.player.inventory.canFit({ itemId: itemIdToAdd, amount: countToRemove })) { details.player.sendMessage('Your inventory is full.'); return; } const itemToAdd: Item = { itemId: itemIdToAdd, amount: 0 }; - while (countToRemove > 0 && otherPlayerInventory.has(details.itemId)) { - const invIndex = otherPlayerInventory.findIndex(details.itemId); - const invItem = otherPlayerInventory.items[invIndex]; + while (countToRemove > 0 && otherPlayer.inventory.has(details.itemId)) { + const invIndex = otherPlayer.inventory.findIndex(details.itemId); + const invItem = otherPlayer.inventory.items[invIndex]; + + if (!invItem) { + logger.error(`Could not find item ${details.itemId} in inventory at slot ${invIndex} in rotten potato`); + return; + } + if (countToRemove >= invItem.amount) { itemToAdd.amount += invItem.amount; countToRemove -= invItem.amount; - otherPlayerInventory.remove(invIndex); + otherPlayer.inventory.remove(invIndex); } else { itemToAdd.amount += countToRemove; invItem.amount -= countToRemove; @@ -74,11 +90,10 @@ export const potatoManipulatePlayerInventory: itemInteractionActionHandler = (de } } - playerInventory.addStacking(itemToAdd); + details.player.inventory.addStacking(itemToAdd); details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.depositBoxWidget, otherPlayer.inventory); details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, details.player.inventory); otherPlayer.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, otherPlayer.inventory); }; - diff --git a/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts b/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts index aff77e332..24f7ccc72 100644 --- a/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts +++ b/src/plugins/items/rotten-potato/hooks/rotten-potato-peel.ts @@ -1,9 +1,9 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action/pipe/item-interaction.action'; import { Player } from '@engine/world/actor/player/player'; import { dialogue, execute } from '@engine/world/actor/dialogue'; -import { getActionHooks } from '@engine/world/action/hooks'; -import { advancedNumberHookFilter } from '@engine/world/action/hooks/hook-filters'; -import { ObjectInteractionActionHook } from '@engine/world/action/object-interaction.action'; +import { getActionHooks } from '@engine/action/hook'; +import { advancedNumberHookFilter } from '@engine/action/hook/hook-filters'; +import { ObjectInteractionActionHook } from '@engine/action/pipe/object-interaction.action'; import { objectIds } from '@engine/world/config/object-ids'; import { openTravel } from '@plugins/items/rotten-potato/helpers/rotten-potato-travel'; @@ -11,7 +11,11 @@ import { openTravel } from '@plugins/items/rotten-potato/helpers/rotten-potato-t function openBank(player: Player) { const interactionActions = getActionHooks('object_interaction') .filter(plugin => advancedNumberHookFilter(plugin.objectIds, objectIds.bankBooth, plugin.options, 'use-quickly')); - interactionActions.forEach(plugin => + interactionActions.forEach(plugin => { + if (!plugin.handler) { + return; + } + plugin.handler({ player: player, object: { @@ -22,11 +26,12 @@ function openBank(player: Player) { orientation: 0, type: 0 }, - objectConfig: undefined, option: 'use-quickly', position: player.position, - cacheOriginal: undefined - })); + objectConfig: undefined as any, + cacheOriginal: undefined as any + }) + }); } enum DialogueOption { @@ -56,7 +61,10 @@ const peelPotato: itemInteractionActionHandler = async (details) => { // ], ] ]); - switch (chosenOption) { + + // using ! here because we have just set it in the dialogue + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + switch (chosenOption!) { case DialogueOption.BANK: openBank(details.player); break; diff --git a/src/plugins/items/rotten-potato/rotten-potato.plugin.ts b/src/plugins/items/rotten-potato/rotten-potato.plugin.ts index b402b50ec..f084859a9 100644 --- a/src/plugins/items/rotten-potato/rotten-potato.plugin.ts +++ b/src/plugins/items/rotten-potato/rotten-potato.plugin.ts @@ -1,4 +1,4 @@ -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; import spawnPotato from '@plugins/items/rotten-potato/hooks/rotten-potato-command-hook'; import itemOnPotato from '@plugins/items/rotten-potato/hooks/rotten-potato-item-on-item'; import { ExecuteIfAdmin, RottenPotatoItem } from '@plugins/items/rotten-potato/helpers/rotten-potato-helpers'; @@ -6,7 +6,7 @@ import peelPotato from '@plugins/items/rotten-potato/hooks/rotten-potato-peel'; import { potatoOnPlayer, potatoManipulatePlayerInventory } from '@plugins/items/rotten-potato/hooks/rotten-potato-item-on-player'; import eatPotato from '@plugins/items/rotten-potato/hooks/rotten-potato-eat'; import { travelMenuInteract } from '@plugins/items/rotten-potato/helpers/rotten-potato-travel'; -import { WidgetInteractionActionHook } from '@engine/world/action/widget-interaction.action'; +import { WidgetInteractionActionHook } from '@engine/action'; export default { pluginId: 'promises:rotten-potato', diff --git a/src/plugins/items/runecrafting/tiaras.plugin.ts b/src/plugins/items/runecrafting/tiaras.plugin.ts index e6cffcc0b..76e4eb413 100644 --- a/src/plugins/items/runecrafting/tiaras.plugin.ts +++ b/src/plugins/items/runecrafting/tiaras.plugin.ts @@ -1,4 +1,4 @@ -import { equipmentChangeActionHandler } from '@engine/world/action/equipment-change.action'; +import { equipmentChangeActionHandler } from '@engine/action'; export const equip: equipmentChangeActionHandler = (details) => { const { player } = details; diff --git a/src/plugins/items/shopping/buy-from-shop.plugin.ts b/src/plugins/items/shopping/buy-from-shop.plugin.ts index de414bae8..d105d5bad 100644 --- a/src/plugins/items/shopping/buy-from-shop.plugin.ts +++ b/src/plugins/items/shopping/buy-from-shop.plugin.ts @@ -1,13 +1,19 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; import { Item } from '@engine/world/items/item'; import { getItemFromContainer, ItemContainer } from '@engine/world/items/item-container'; import { itemIds } from '@engine/world/config/item-ids'; -import { findItem, widgets } from '@engine/config'; -import { Shop } from '@engine/config/shop-config'; +import { findItem, widgets } from '@engine/config/config-handler'; +import { logger } from '@runejs/common'; function removeCoins(inventory: ItemContainer, coinsIndex: number, cost: number): void { const coins = inventory.items[coinsIndex]; + + if (!coins) { + logger.error(`Could not find coins in inventory at slot ${coinsIndex} while trying to remove coins`); + return; + } + const amountAfterPurchase = coins.amount - cost; inventory.set(coinsIndex, { itemId: itemIds.coins, amount: amountAfterPurchase }); } @@ -19,7 +25,7 @@ export const handler: itemInteractionActionHandler = (details) => { return; } - const openedShop: Shop = player.metadata['lastOpenedShop']; + const openedShop = player.metadata.lastOpenedShop; if(!openedShop) { return; } @@ -48,6 +54,12 @@ export const handler: itemInteractionActionHandler = (details) => { } const buyItem = findItem(itemId); + + if(!buyItem) { + logger.error(`Could not find cache item for item id ${itemId} in shop ${openedShop.id}`); + return; + } + const buyItemValue = buyItem.value || 0; let buyCost = buyAmount * buyItemValue; const coinsIndex = player.hasCoins(buyCost); @@ -69,6 +81,12 @@ export const handler: itemInteractionActionHandler = (details) => { } } else { const inventoryItem = inventory.items[inventoryStackSlot]; + + if (!inventoryItem) { + logger.error(`Coult not find inventory item at slot ${inventoryStackSlot} for player ${player.username} while trying to stack`); + return; + } + if(inventoryItem.amount + buyAmount >= 2147483647) { player.sendMessage(`You don't have enough space in your inventory.`); return; diff --git a/src/plugins/items/shopping/item-value.plugin.ts b/src/plugins/items/shopping/item-value.plugin.ts index 5c56a78bc..d4ce78a1b 100644 --- a/src/plugins/items/shopping/item-value.plugin.ts +++ b/src/plugins/items/shopping/item-value.plugin.ts @@ -1,6 +1,6 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; import { Shop } from '@engine/config/shop-config'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; export const shopSellValueHandler: itemInteractionActionHandler = ({ player, itemDetails }) => { const itemValue = itemDetails.value || 1; @@ -8,7 +8,7 @@ export const shopSellValueHandler: itemInteractionActionHandler = ({ player, ite }; export const shopPurchaseValueHandler: itemInteractionActionHandler = ({ player, itemDetails }) => { - const openedShop: Shop = player.metadata['lastOpenedShop']; + const openedShop = player.metadata.lastOpenedShop; if(!openedShop) { return; } diff --git a/src/plugins/items/shopping/sell-to-shop.plugin.ts b/src/plugins/items/shopping/sell-to-shop.plugin.ts index 523f388f2..6d9294115 100644 --- a/src/plugins/items/shopping/sell-to-shop.plugin.ts +++ b/src/plugins/items/shopping/sell-to-shop.plugin.ts @@ -1,8 +1,7 @@ -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; import { itemIds } from '@engine/world/config/item-ids'; import { getItemFromContainer } from '@engine/world/items/item-container'; -import { Shop } from '@engine/config/shop-config'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; export const handler: itemInteractionActionHandler = (details) => { @@ -12,7 +11,7 @@ export const handler: itemInteractionActionHandler = (details) => { return; } - const openedShop: Shop = player.metadata['lastOpenedShop']; + const openedShop = player.metadata.lastOpenedShop; if(!openedShop) { return; } @@ -56,7 +55,13 @@ export const handler: itemInteractionActionHandler = (details) => { } for(let i = 0; i < sellAmount; i++) { - inventory.remove(foundItems[i]); + const item = foundItems[i]; + + if (!item) { + throw new Error(`Inventory item was not present, for item id ${itemId} in inventory, while trying to sell`); + } + + inventory.remove(item); } } @@ -76,7 +81,9 @@ export const handler: itemInteractionActionHandler = (details) => { coinsIndex = inventory.getFirstOpenSlot(); inventory.set(coinsIndex, { itemId: itemIds.coins, amount: sellPrice }); } else { - inventory.items[coinsIndex].amount += sellPrice; + // TODO (Jameskmonger) consider being explicit to prevent dupes + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + inventory.items[coinsIndex]!.amount += sellPrice; } } diff --git a/src/plugins/items/swap-items.plugin.ts b/src/plugins/items/swap-items.plugin.ts index 85b3d2b20..7c0269990 100644 --- a/src/plugins/items/swap-items.plugin.ts +++ b/src/plugins/items/swap-items.plugin.ts @@ -1,7 +1,7 @@ -import { itemSwapActionHandler } from '@engine/world/action/item-swap.action'; +import { itemSwapActionHandler } from '@engine/action'; import { ItemContainer } from '@engine/world/items/item-container'; import { Player } from '@engine/world/actor/player/player'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; type WidgetDetail = [ number, number, (player: Player) => ItemContainer ]; diff --git a/src/plugins/music/music-regions.plugin.ts b/src/plugins/music/music-regions.plugin.ts index 933a0e292..1f4544017 100644 --- a/src/plugins/music/music-regions.plugin.ts +++ b/src/plugins/music/music-regions.plugin.ts @@ -1,7 +1,7 @@ -import { findMusicTrack, findSongIdByRegionId, musicRegionMap, musicRegions, widgets } from '@engine/config'; +import { findMusicTrack, findSongIdByRegionId, musicRegionMap, musicRegions, widgets } from '@engine/config/config-handler'; import { colors } from '@engine/util/colors'; -import { MusicPlayerMode } from '@plugins/music/music-tab.plugin'; -import { playerInitActionHandler } from '@engine/world/action/player-init.action'; +import { playerInitActionHandler } from '@engine/action'; +import { MusicPlayerMode } from '@engine/world/sound'; musicRegions.forEach(song => song.regionIds.forEach(region => musicRegionMap.set(region, song.songId))); @@ -14,16 +14,23 @@ function getByValue(map, searchValue) { } const regionChangedHandler = ({ player, currentMapRegionId }): void => { - const songId: number = findSongIdByRegionId(currentMapRegionId); + const songId = findSongIdByRegionId(currentMapRegionId); if(songId == null) { return; } - const songName = findMusicTrack(songId).songName; + + const musicTrack = findMusicTrack(songId) + + if (!musicTrack) { + return; + } + + const songName = musicTrack.songName; // player.sendMessage(`Playing ${songId}:${getByValue(songs, songId)} at region ${currentMapRegionId}`); if(!player.musicTracks.includes(songId)) { player.musicTracks.push(songId); player.sendMessage('You have unlocked a new music track: ' + songName + '.'); - player.modifyWidget(widgets.musicPlayerTab, { childId: findMusicTrack(songId).musicTabButtonId, textColor: colors.green }); + player.modifyWidget(widgets.musicPlayerTab, { childId: musicTrack.musicTabButtonId, textColor: colors.green }); } if(player.settings.musicPlayerMode === MusicPlayerMode.AUTO) { player.playSong(songId); diff --git a/src/plugins/music/music-tab.plugin.ts b/src/plugins/music/music-tab.plugin.ts index da8a38001..682fb9809 100644 --- a/src/plugins/music/music-tab.plugin.ts +++ b/src/plugins/music/music-tab.plugin.ts @@ -1,7 +1,9 @@ -import { buttonActionHandler } from '@engine/world/action/button.action'; -import { widgets, findMusicTrackByButtonId, findSongIdByRegionId } from '@engine/config'; -import { widgetScripts } from '@engine/world/config/widget'; -import { world } from '@engine/game-server'; +import { buttonActionHandler } from '@engine/action'; +import { findMusicTrackByButtonId, findSongIdByRegionId, widgets } from '@engine/config'; +import { widgetScripts } from '@engine/world/config'; +import { MusicPlayerMode, MusicTabButtonIds } from '@engine/world/sound'; +import { activeWorld } from '@engine/world'; +import { logger } from '@runejs/common'; export const handler: buttonActionHandler = (details) => { const { player, buttonId } = details; @@ -9,7 +11,12 @@ export const handler: buttonActionHandler = (details) => { if(buttonId === MusicTabButtonIds.AUTO_BUTTON_ID) { player.settings.musicPlayerMode = MusicPlayerMode.AUTO; const songIdForCurrentRegion = findSongIdByRegionId( - world.chunkManager.getRegionIdForWorldPosition(player.position)); + activeWorld.chunkManager.getRegionIdForWorldPosition(player.position)); + + if (!songIdForCurrentRegion) { + logger.warn(`No song found for current region`); + return; + } if(player.savedMetadata['currentSongIdPlaying'] !== songIdForCurrentRegion) { player.playSong(songIdForCurrentRegion); @@ -32,22 +39,6 @@ export const handler: buttonActionHandler = (details) => { } }; -export enum MusicPlayerMode { - MANUAL = 0, - AUTO = 1 -} - -export enum MusicPlayerLoopMode { - ENABLED = 0, - DISABLED = 1 -} - -export enum MusicTabButtonIds { - AUTO_BUTTON_ID = 180, - MANUAL_BUTTON_ID = 181, - LOOP_BUTTON_ID = 251 -} - export default { pluginId: 'rs:music_tab', hooks: [ diff --git a/src/plugins/npcs/al-kharid/dommik-crafting-shop.plugin.ts b/src/plugins/npcs/al-kharid/dommik-crafting-shop.plugin.ts index 2cc92cc0c..e0a2c995d 100644 --- a/src/plugins/npcs/al-kharid/dommik-crafting-shop.plugin.ts +++ b/src/plugins/npcs/al-kharid/dommik-crafting-shop.plugin.ts @@ -1,6 +1,6 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action'; import { dialogueAction, DialogueEmote } from '@engine/world/actor/player/dialogue-action'; -import { findShop } from '@engine/config'; +import { findShop } from '@engine/config/config-handler'; const tradeAction: npcInteractionActionHandler = ({ player }) => diff --git a/src/plugins/npcs/al-kharid/gem-trader.plugin.ts b/src/plugins/npcs/al-kharid/gem-trader.plugin.ts index 06d8dae7f..07e4e0860 100644 --- a/src/plugins/npcs/al-kharid/gem-trader.plugin.ts +++ b/src/plugins/npcs/al-kharid/gem-trader.plugin.ts @@ -1,6 +1,6 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action'; import { dialogueAction, DialogueEmote } from '@engine/world/actor/player/dialogue-action'; -import { findShop } from '@engine/config'; +import { findShop } from '@engine/config/config-handler'; const tradeAction: npcInteractionActionHandler = ({ player }) => diff --git a/src/plugins/npcs/al-kharid/karim.plugin.ts b/src/plugins/npcs/al-kharid/karim.plugin.ts index 16ece86f9..5933ace13 100644 --- a/src/plugins/npcs/al-kharid/karim.plugin.ts +++ b/src/plugins/npcs/al-kharid/karim.plugin.ts @@ -1,7 +1,8 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action'; import { itemIds } from '@engine/world/config/item-ids'; import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; +import { logger } from '@runejs/common'; const talkToAction : npcInteractionActionHandler = (details) => { const { player, npc } = details; @@ -25,6 +26,11 @@ const talkToAction : npcInteractionActionHandler = (details) => { return; } + if (!item) { + logger.warn(`Could not find item with id ${itemIds.coins} in player inventory. [Karim plugin]`); + return; + } + inventory.remove(index); if (item.amount !== 1) { inventory.add( { itemId: itemIds.coins, amount: item.amount - 1 }); diff --git a/src/plugins/npcs/al-kharid/louie-armoured-legs.plugin.ts b/src/plugins/npcs/al-kharid/louie-armoured-legs.plugin.ts index 8fbce70c7..6452ea84d 100644 --- a/src/plugins/npcs/al-kharid/louie-armoured-legs.plugin.ts +++ b/src/plugins/npcs/al-kharid/louie-armoured-legs.plugin.ts @@ -1,5 +1,5 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; -import { findShop } from '@engine/config'; +import { npcInteractionActionHandler } from '@engine/action'; +import { findShop } from '@engine/config/config-handler'; const tradeAction: npcInteractionActionHandler = ({ player }) => diff --git a/src/plugins/npcs/al-kharid/ranael-super-skirt.plugin.ts b/src/plugins/npcs/al-kharid/ranael-super-skirt.plugin.ts index 05a5cb0e7..f132e3fa3 100644 --- a/src/plugins/npcs/al-kharid/ranael-super-skirt.plugin.ts +++ b/src/plugins/npcs/al-kharid/ranael-super-skirt.plugin.ts @@ -1,5 +1,5 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; -import { findShop } from '@engine/config'; +import { npcInteractionActionHandler } from '@engine/action'; +import { findShop } from '@engine/config/config-handler'; const tradeAction: npcInteractionActionHandler = ({ player }) => diff --git a/src/plugins/npcs/falador/custom-guards.plugin.ts b/src/plugins/npcs/falador/custom-guards.plugin.ts index 4f1c19045..e91483fb5 100644 --- a/src/plugins/npcs/falador/custom-guards.plugin.ts +++ b/src/plugins/npcs/falador/custom-guards.plugin.ts @@ -1,12 +1,14 @@ -import { npcInitActionHandler } from '@engine/world/action/npc-init.action'; +import { npcInitActionHandler } from '@engine/action'; import { World } from '@engine/world'; import { Position } from '@engine/world/position'; -import { world } from '@engine/game-server'; -import { findNpc } from '@engine/config'; -import { Npc } from '@engine/world/actor/npc/npc'; +import { findNpc } from '@engine/config/config-handler'; +import { Npc } from '@engine/world/actor/npc'; import { randomBetween } from '@engine/util/num'; +import { activeWorld } from '@engine/world'; + const npcs = ['rs:guard:0', 'rs:guard:1'] -const npcObjects = npcs.map((sNpc) => findNpc(sNpc)); +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion +const npcObjects = npcs.map((sNpc) => findNpc(sNpc)!); interface DialogueNpcTree { a?: string; @@ -163,7 +165,7 @@ function doDialogue(a: Npc, b: Npc, dialogueIndex: number, dialogueTree: Dialogu const npcIdleAction = (npc: Npc) => { if(Math.random() >= 0.14) { const currentLocation = new Position(npc.position); - const closeNpcs = world.findNearbyNpcs(currentLocation, 4); + const closeNpcs = activeWorld.findNearbyNpcs(currentLocation, 4); for (const closeNpc of closeNpcs) { if(closeNpc === npc) { continue; diff --git a/src/plugins/npcs/lumbridge/bob.plugin.ts b/src/plugins/npcs/lumbridge/bob.plugin.ts index f4f4fbc62..2d866eae3 100644 --- a/src/plugins/npcs/lumbridge/bob.plugin.ts +++ b/src/plugins/npcs/lumbridge/bob.plugin.ts @@ -1,19 +1,19 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { ContentPlugin } from '@engine/plugins'; +import { NpcInteractionActionHook } from '@engine/action'; import { findShop } from '@engine/config'; -const action: npcInteractionActionHandler = ({ player }) => - findShop('rs:lumbridge_bobs_axes')?.open(player); +const bobHook: NpcInteractionActionHook = { + type: 'npc_interaction', + npcs: 'rs:lumbridge_bob', + options: 'trade', + walkTo: true, + handler: ({ player }) => findShop('rs:lumbridge_bobs_axes')?.open(player) +}; -export default { +const bobPlugin: ContentPlugin = { pluginId: 'rs:bob', - hooks: [ - { - type: 'npc_interaction', - npcs: 'rs:lumbridge_bob', - options: 'trade', - walkTo: true, - handler: action - } - ] -}; + hooks: [ bobHook ] +} + +export default bobPlugin; diff --git a/src/plugins/npcs/lumbridge/hans.plugin.js b/src/plugins/npcs/lumbridge/hans.plugin.ts similarity index 80% rename from src/plugins/npcs/lumbridge/hans.plugin.js rename to src/plugins/npcs/lumbridge/hans.plugin.ts index 990e35c00..6cb74431c 100644 --- a/src/plugins/npcs/lumbridge/hans.plugin.js +++ b/src/plugins/npcs/lumbridge/hans.plugin.ts @@ -1,12 +1,15 @@ -import { dialogue, Emote, goto, execute } from '../../../game-engine/world/actor/dialogue'; -import { animationIds } from '../../../game-engine/world/config/animation-ids'; -import { Achievements, giveAchievement } from '../../../game-engine/world/actor/player/achievements'; +import { NpcInteractionActionHook } from '@engine/action'; +import { Emote, goto, execute, Achievements, giveAchievement } from '@engine/world/actor'; +import { animationIds } from '@engine/world/config'; +import { dialogue } from '@engine/world/actor/dialogue'; const handler = async ({ player, npc }) => { let sadEnding = false; - const dialogueSuccessful = await dialogue([ player, { npc, key: 'hans' } ], [ + const dialogueParticipants = [ player, { npc, key: 'hans' }]; + + const dialogueTree = [ hans => [ Emote.GENERIC, `Welcome to RuneJS!` ], (hans, tag_Hans_Question) => [ Emote.HAPPY, `How do you feel about RuneJS so far?\n` + `Please take a moment to let us know what you think!` ], @@ -33,7 +36,9 @@ const handler = async ({ player, npc }) => { goto('tag_Hans_Question') ] ]) - ]); + ]; + + const dialogueSuccessful = await dialogue(dialogueParticipants, dialogueTree); npc.clearFaceActor(); player.clearFaceActor(); @@ -52,7 +57,7 @@ const handler = async ({ player, npc }) => { }; -module.exports = { +export default { pluginId: 'rs:hans', hooks: [ { @@ -61,6 +66,6 @@ module.exports = { options: 'talk-to', walkTo: true, handler - } + } as NpcInteractionActionHook ] }; diff --git a/src/plugins/npcs/lumbridge/lumbridge-farm-helpers.plugin.ts b/src/plugins/npcs/lumbridge/lumbridge-farm-helpers.plugin.ts index c5150a8e5..aeab4135c 100644 --- a/src/plugins/npcs/lumbridge/lumbridge-farm-helpers.plugin.ts +++ b/src/plugins/npcs/lumbridge/lumbridge-farm-helpers.plugin.ts @@ -1,4 +1,4 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action'; import { dialogue, Emote, goto } from '@engine/world/actor/dialogue'; const millieDialogue: npcInteractionActionHandler = async (details) => diff --git a/src/plugins/npcs/lumbridge/shopkeeper.plugin.ts b/src/plugins/npcs/lumbridge/shopkeeper.plugin.ts index 7a3aa8cf3..94e0e57bf 100644 --- a/src/plugins/npcs/lumbridge/shopkeeper.plugin.ts +++ b/src/plugins/npcs/lumbridge/shopkeeper.plugin.ts @@ -1,5 +1,5 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; -import { findShop } from '@engine/config'; +import { npcInteractionActionHandler } from '@engine/action'; +import { findShop } from '@engine/config/config-handler'; const action: npcInteractionActionHandler = ({ player }) => { diff --git a/src/plugins/npcs/port-sarim/betty.plugin.ts b/src/plugins/npcs/port-sarim/betty.plugin.ts index e78099af8..3394a4087 100644 --- a/src/plugins/npcs/port-sarim/betty.plugin.ts +++ b/src/plugins/npcs/port-sarim/betty.plugin.ts @@ -1,5 +1,5 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; -import { findShop } from '@engine/config'; +import { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; +import { findShop } from '@engine/config/config-handler'; import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; diff --git a/src/plugins/npcs/varrock/blue-moon-inn.plugin.ts b/src/plugins/npcs/varrock/blue-moon-inn.plugin.ts index 8287a45b9..ba3441189 100644 --- a/src/plugins/npcs/varrock/blue-moon-inn.plugin.ts +++ b/src/plugins/npcs/varrock/blue-moon-inn.plugin.ts @@ -1,7 +1,7 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action'; import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; import { itemIds } from '@engine/world/config/item-ids'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; const talkToBartender : npcInteractionActionHandler = (details) => { diff --git a/src/plugins/npcs/varrock/master-smithing-tutor.plugin.ts b/src/plugins/npcs/varrock/master-smithing-tutor.plugin.ts index 1d6d99dd2..3e2e84ebd 100644 --- a/src/plugins/npcs/varrock/master-smithing-tutor.plugin.ts +++ b/src/plugins/npcs/varrock/master-smithing-tutor.plugin.ts @@ -1,7 +1,7 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action'; import { dialogue, Emote, execute, goto } from '@engine/world/actor/dialogue'; import { itemIds } from '@engine/world/config/item-ids'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; const talkTo : npcInteractionActionHandler = (details) => { diff --git a/src/plugins/npcs/varrock/wilough.plugin.ts b/src/plugins/npcs/varrock/wilough.plugin.ts index 42d863f16..a59870f56 100644 --- a/src/plugins/npcs/varrock/wilough.plugin.ts +++ b/src/plugins/npcs/varrock/wilough.plugin.ts @@ -1,11 +1,13 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action'; import { dialogue, Emote } from '@engine/world/actor/dialogue'; -import { findNpc } from '@engine/config'; +import { findNpc } from '@engine/config/config-handler'; const talkTo : npcInteractionActionHandler = (details) => { const { player, npc } = details; - dialogue([player, { npc, key: 'wilough' }, { npc: findNpc('rs:varrock_shilop').gameId, key: 'shilop' }], [ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const shilop = findNpc('rs:varrock_shilop')!; + dialogue([player, { npc, key: 'wilough' }, { npc: shilop.gameId, key: 'shilop' }], [ player => [Emote.GENERIC, `Hello again.`], wilough => [Emote.GENERIC, `You think you're tough do you?`], player => [Emote.GENERIC, `Pardon?`], diff --git a/src/plugins/npcs/varrock/zaff-superior-staffs.plugin.ts b/src/plugins/npcs/varrock/zaff-superior-staffs.plugin.ts index 0d4c5acec..ad4bf5eca 100644 --- a/src/plugins/npcs/varrock/zaff-superior-staffs.plugin.ts +++ b/src/plugins/npcs/varrock/zaff-superior-staffs.plugin.ts @@ -1,6 +1,6 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action'; import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; -import { findShop } from '@engine/config'; +import { findShop } from '@engine/config/config-handler'; const tradeAction: npcInteractionActionHandler = ({ player }) => diff --git a/src/plugins/objects/bank/bank.plugin.ts b/src/plugins/objects/bank/bank.plugin.ts index 34432164c..3c49247a1 100644 --- a/src/plugins/objects/bank/bank.plugin.ts +++ b/src/plugins/objects/bank/bank.plugin.ts @@ -1,13 +1,14 @@ import { objectIds } from '@engine/world/config/object-ids'; import { widgetScripts } from '@engine/world/config/widget'; -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { ItemContainer } from '@engine/world/items/item-container'; -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; import { fromNote, Item, toNote } from '@engine/world/items/item'; -import { buttonActionHandler } from '@engine/world/action/button.action'; +import { buttonActionHandler } from '@engine/action'; import { dialogue, Emote, execute } from '@engine/world/actor/dialogue'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; import { Player } from '@engine/world/actor/player/player'; +import { logger } from '@runejs/common'; const buttonIds: number[] = [ @@ -79,11 +80,24 @@ export const depositItem: itemInteractionActionHandler = (details) => { throw new Error('Unhandled option in banking plugin: ' + details.option); } - const playerInventory: ItemContainer = details.player.inventory; - const playerBank: ItemContainer = details.player.bank; - const slotsWithItem: number[] = playerInventory.findAll(details.itemId); - let itemAmount: number = 0; - slotsWithItem.forEach((slot) => itemAmount += playerInventory.items[slot].amount); + const playerInventory = details.player.inventory; + const playerBank = details.player.bank; + const slotsWithItem = playerInventory.findAll(details.itemId); + + let itemAmount = 0; + slotsWithItem.forEach((slot) => { + const item = playerInventory.items[slot]; + + if (!item) { + throw new Error(`Container item was not present, for item id ${details.itemId} in inventory, while trying to deposit`); + } + + if (item.itemId !== details.itemId) { + throw new Error(`Container item id mismatch, for item id ${details.itemId} in inventory, while trying to deposit`); + } + + itemAmount += item.amount; + }); if (countToRemove === -1 || countToRemove > itemAmount) { countToRemove = itemAmount; } @@ -114,10 +128,12 @@ export const withdrawItem: itemInteractionActionHandler = (details) => { } let itemIdToAdd: number = details.itemId; + let stackable: boolean = details.itemDetails.stackable; if (details.player.settings.bankWithdrawNoteMode) { const toNoteId: number = toNote(details.itemId); if (toNoteId > -1) { itemIdToAdd = toNoteId; + stackable = true; } else { details.player.sendMessage('This item can not be withdrawn as a note.'); } @@ -146,15 +162,22 @@ export const withdrawItem: itemInteractionActionHandler = (details) => { throw new Error('Unhandled option in banking plugin: ' + details.option); } - const playerBank: ItemContainer = details.player.bank; - const playerInventory: ItemContainer = details.player.inventory; - const slotWithItem: number = playerBank.findIndex(details.itemId); - const itemAmount: number = playerBank.items[slotWithItem].amount; + const playerBank = details.player.bank; + const playerInventory = details.player.inventory; + const slotWithItem = playerBank.findIndex(details.itemId); + const itemInBank = playerBank.items[slotWithItem]; + + if (!itemInBank) { + logger.error(`Container item was not present, for item id ${details.itemId} in bank, while trying to withdraw`); + return; + } + + const itemAmount = itemInBank.amount; if (countToRemove === -1 || countToRemove > itemAmount) { countToRemove = itemAmount; } - if (!details.itemDetails.stackable) { + if (!stackable) { const slots = playerInventory.getOpenSlotCount(); if (slots < countToRemove) { countToRemove = slots; @@ -170,7 +193,13 @@ export const withdrawItem: itemInteractionActionHandler = (details) => { amount: removeFromContainer(playerBank, details.itemId, countToRemove) }; - playerInventory.add({ itemId: itemToAdd.itemId, amount: itemToAdd.amount }); + if (stackable) { + playerInventory.add({ itemId: itemToAdd.itemId, amount: itemToAdd.amount }); + } else { + for(let count = 0; count < itemToAdd.amount; count++) { + playerInventory.add({ itemId: itemToAdd.itemId, amount: 1 }); + } + } updateBankingInterface(details.player); }; @@ -196,6 +225,10 @@ export const removeFromContainer = (from: ItemContainer, itemId: number, amount: const containerIndex = from.findIndex(itemId); const containerItem = from.items[containerIndex]; + if (!containerItem) { + throw new Error(`Container item was not present, for item id ${itemId} in bank, while trying to remove`); + } + if (removeAmount >= containerItem.amount) { resultingAmount += containerItem.amount; removeAmount -= containerItem.amount; diff --git a/src/plugins/objects/bank/deposit-box.plugin.ts b/src/plugins/objects/bank/deposit-box.plugin.ts index 1747edf41..99c8872b5 100644 --- a/src/plugins/objects/bank/deposit-box.plugin.ts +++ b/src/plugins/objects/bank/deposit-box.plugin.ts @@ -1,9 +1,9 @@ import { objectIds } from '@engine/world/config/object-ids'; -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { ItemContainer } from '@engine/world/items/item-container'; -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; import { fromNote, Item } from '@engine/world/items/item'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; export const openDepositBoxInterface: objectInteractionActionHandler = ({ player }) => { @@ -48,11 +48,24 @@ export const depositItem: itemInteractionActionHandler = (details) => { } - const playerInventory: ItemContainer = details.player.inventory; - const playerBank: ItemContainer = details.player.bank; - const slotsWithItem: number[] = playerInventory.findAll(details.itemId); + const playerInventory = details.player.inventory; + const playerBank = details.player.bank; + const slotsWithItem = playerInventory.findAll(details.itemId); + let itemAmount: number = 0; - slotsWithItem.forEach((slot) => itemAmount += playerInventory.items[slot].amount); + slotsWithItem.forEach((slot) => { + const item = playerInventory.items[slot]; + + if (!item) { + throw new Error(`Container item was not present, for item id ${details.itemId} in inventory, while trying to deposit`); + } + + if (item.itemId !== details.itemId) { + throw new Error(`Container item id mismatch, for item id ${details.itemId} in inventory, while trying to deposit`); + } + + itemAmount += item.amount; + }); if (countToRemove == -1 || countToRemove > itemAmount) { countToRemove = itemAmount; } @@ -67,6 +80,11 @@ export const depositItem: itemInteractionActionHandler = (details) => { while (countToRemove > 0 && playerInventory.has(details.itemId)) { const invIndex = playerInventory.findIndex(details.itemId); const invItem = playerInventory.items[invIndex]; + + if (!invItem) { + throw new Error(`Inventory item was not present, for item id ${details.itemId} in bank, while trying to deposit`); + } + if (countToRemove >= invItem.amount) { itemToAdd.amount += invItem.amount; countToRemove -= invItem.amount; diff --git a/src/plugins/objects/cows/cow.plugin.ts b/src/plugins/objects/cows/cow.plugin.ts index 4760f122f..e9b5da3cd 100644 --- a/src/plugins/objects/cows/cow.plugin.ts +++ b/src/plugins/objects/cows/cow.plugin.ts @@ -1,18 +1,19 @@ -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { dialogueAction, DialogueEmote } from '@engine/world/actor/player/dialogue-action'; import { animationIds } from '@engine/world/config/animation-ids'; import { soundIds } from '@engine/world/config/sound-ids'; import { itemIds } from '@engine/world/config/item-ids'; import { objectIds } from '@engine/world/config/object-ids'; -import { itemOnObjectActionHandler } from '@engine/world/action/item-on-object.action'; +import { itemOnObjectActionHandler } from '@engine/action'; import { Player } from '@engine/world/actor/player/player'; -import { findItem, findNpc } from '@engine/config'; +import { findItem, findNpc } from '@engine/config/config-handler'; import { ObjectConfig } from '@runejs/filestore'; function milkCow(details: { objectConfig: ObjectConfig, player: Player }): void { const { player, objectConfig } = details; - const emptyBucketItem = findItem(itemIds.bucket); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const emptyBucketItem = findItem(itemIds.bucket)!; if (player.hasItemInInventory(itemIds.bucket)) { player.playAnimation(animationIds.milkCow); @@ -21,7 +22,8 @@ function milkCow(details: { objectConfig: ObjectConfig, player: Player }): void player.giveItem(itemIds.bucketOfMilk); player.sendMessage(`You milk the ${objectConfig.name} and receive some milk.`); } else { - const gillieId = findNpc('rs:gillie_groats').gameId; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const gillieId = findNpc('rs:gillie_groats')!.gameId; dialogueAction(player) .then(async d => d.npc(gillieId, DialogueEmote.LAUGH_1, [`Tee hee! You've never milked a cow before, have you?`])) .then(async d => d.player(DialogueEmote.CALM_TALK_1, ['Erm... No. How could you tell?'])) diff --git a/src/plugins/objects/crates/crates.plugin.ts b/src/plugins/objects/crates/crates.plugin.ts index eb0d9aa49..4d8d7cc9a 100644 --- a/src/plugins/objects/crates/crates.plugin.ts +++ b/src/plugins/objects/crates/crates.plugin.ts @@ -1,17 +1,17 @@ -import { findItem, widgets } from '@engine/config'; -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { findItem, widgets } from '@engine/config/config-handler'; +import { objectInteractionActionHandler } from '@engine/action'; import { World } from '@engine/world'; import { itemIds } from '@engine/world/config/item-ids'; -import { LandscapeObject } from '@runejs/filestore'; export const action: objectInteractionActionHandler = (details) => { const veggies = [itemIds.onion, itemIds.grain, itemIds.cabbage]; details.player.busy = true; details.player.playAnimation(827); - - const random = Math.floor(Math.random() * 3); - const pickedItem = findItem(veggies[random]); - + + const random = Math.floor(Math.random() * veggies.length); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const pickedItem = findItem(veggies[random])!; + details.player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, details.player.inventory); setTimeout(() => { diff --git a/src/plugins/objects/doors/door.plugin.ts b/src/plugins/objects/doors/door.plugin.ts index 5c9f3fac3..02622a77e 100644 --- a/src/plugins/objects/doors/door.plugin.ts +++ b/src/plugins/objects/doors/door.plugin.ts @@ -1,5 +1,5 @@ import { directionData, WNES } from '@engine/world/direction'; -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { soundIds } from '@engine/world/config/sound-ids'; import { LandscapeObject } from '@runejs/filestore'; diff --git a/src/plugins/objects/doors/double-door.plugin.ts b/src/plugins/objects/doors/double-door.plugin.ts index c931c32ff..c8ff9d187 100644 --- a/src/plugins/objects/doors/double-door.plugin.ts +++ b/src/plugins/objects/doors/double-door.plugin.ts @@ -1,9 +1,9 @@ import { Position } from '@engine/world/position'; import { WNES } from '@engine/world/direction'; -import { logger } from '@runejs/core'; -import { world } from '@engine/game-server'; +import { logger } from '@runejs/common'; import { action as doorAction } from '@plugins/objects/doors/door.plugin'; -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; +import { activeWorld } from '@engine/world'; const doubleDoors = [ { @@ -74,22 +74,23 @@ const action: objectInteractionActionHandler = (details) => { const otherDoorPosition = new Position(door.x + deltaX, door.y + deltaY, door.level); - const { object: otherDoor } = world.findObjectAtLocation(player, otherDoorId, otherDoorPosition); + const { object: otherDoor } = activeWorld.findObjectAtLocation(player, otherDoorId, otherDoorPosition); if(!otherDoor) { return; } + // TODO (Jameskmonger) fix the 'as any' here, I used it to satisfy TypeScript strict checks doorAction({ player, object: door, - objectConfig: null, + objectConfig: null as any, position, cacheOriginal, option: opening ? 'open' : 'close' }); doorAction({ player, object: otherDoor, - objectConfig: null, + objectConfig: null as any, position: otherDoorPosition, cacheOriginal, option: opening ? 'open' : 'close' diff --git a/src/plugins/objects/doors/gate.plugin.ts b/src/plugins/objects/doors/gate.plugin.ts index d4dae9178..a68c25ea6 100644 --- a/src/plugins/objects/doors/gate.plugin.ts +++ b/src/plugins/objects/doors/gate.plugin.ts @@ -1,11 +1,11 @@ import { Position } from '@engine/world/position'; import { directionData, WNES } from '@engine/world/direction'; -import { logger } from '@runejs/core'; -import { world } from '@engine/game-server'; +import { logger } from '@runejs/common'; import { ModifiedLandscapeObject } from '@engine/world/map/landscape-object'; -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { soundIds } from '@engine/world/config/sound-ids'; import { Chunk } from '@engine/world/map/chunk'; +import { activeWorld } from '@engine/world'; const gates = [ { @@ -32,6 +32,12 @@ const action: objectInteractionActionHandler = (details) => { if((gate as ModifiedLandscapeObject).metadata) { const metadata = (gate as ModifiedLandscapeObject).metadata; + if (!metadata) { + logger.error(`Could not find metadata for gate with id ${gate.objectId}`); + player.sendMessage('Oops, something went wrong. Please report this to a developer.'); + return; + } + player.instance.toggleGameObjects(metadata.originalMain, metadata.main, true); player.instance.toggleGameObjects(metadata.originalSecond, metadata.second, true); player.playSound(soundIds.closeGate, 7); @@ -42,10 +48,18 @@ const action: objectInteractionActionHandler = (details) => { let hinge; let direction = WNES[gate.orientation]; let hingeChunk: Chunk; - let gateSecondPosition: Position; + let gateSecondPosition: Position | null = null; if(!details) { details = gates.find(g => g.secondary === gate.objectId); + + if(!details) { + logger.error(`Could not find gate details for gate with id ${gate.objectId} on second pass.`); + player.sendMessage('Oops, something went wrong. Please report this to a developer.'); + return; + } + + secondGate = gate; gateSecondPosition = position; clickedSecondary = true; @@ -87,10 +101,19 @@ const action: objectInteractionActionHandler = (details) => { } const pos = new Position(gate.x + deltaX, gate.y + deltaY, gate.level); - hingeChunk = world.chunkManager.getChunkForWorldPosition(pos); - gate = hingeChunk.getFilestoreLandscapeObject(details.main, pos); - direction = WNES[gate.orientation]; - position = pos; + hingeChunk = activeWorld.chunkManager.getChunkForWorldPosition(pos); + + const mainGate = hingeChunk.getFilestoreLandscapeObject(details.main, pos); + + if (mainGate) { + gate = mainGate; + direction = WNES[gate.orientation]; + position = pos; + } else { + logger.error('Could not find main gate for secondary gate at ' + gate.x + ',' + gate.y + ',' + gate.level); + player.sendMessage('Oops, something went wrong. Please report this to a developer.'); + } + } else { hinge = details.hinge; } @@ -164,7 +187,13 @@ const action: objectInteractionActionHandler = (details) => { gateSecondPosition = new Position(gate.x + deltaX, gate.y + deltaY, gate.level); } - const gateSecondChunk = world.chunkManager.getChunkForWorldPosition(gateSecondPosition); + if (!gateSecondPosition) { + logger.error('Improperly handled gate at ' + gate.x + ',' + gate.y + ',' + gate.level); + player.sendMessage('Oops, something went wrong. Please report this to a developer.'); + return; + } + + const gateSecondChunk = activeWorld.chunkManager.getChunkForWorldPosition(gateSecondPosition); if(!clickedSecondary) { secondGate = gateSecondChunk.getFilestoreLandscapeObject(details.secondary, gateSecondPosition); diff --git a/src/plugins/objects/dungeon-entrances/taverly-dungeon-ladder.plugin.ts b/src/plugins/objects/dungeon-entrances/taverly-dungeon-ladder.plugin.ts index 0ccfb88b5..800ba014c 100644 --- a/src/plugins/objects/dungeon-entrances/taverly-dungeon-ladder.plugin.ts +++ b/src/plugins/objects/dungeon-entrances/taverly-dungeon-ladder.plugin.ts @@ -1,4 +1,4 @@ -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { objectIds } from '@engine/world/config/object-ids'; import { World } from '@engine/world'; import { animationIds } from '@engine/world/config/animation-ids'; diff --git a/src/plugins/objects/ladders/ladder.plugin.ts b/src/plugins/objects/ladders/ladder.plugin.ts index 55ed583d8..c14ad433c 100644 --- a/src/plugins/objects/ladders/ladder.plugin.ts +++ b/src/plugins/objects/ladders/ladder.plugin.ts @@ -1,7 +1,8 @@ -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { dialogueAction } from '@engine/world/actor/player/dialogue-action'; import { World } from '@engine/world'; import { Position } from '@engine/world/position'; +import { logger } from '@runejs/common'; const planes = { min: 0, max: 3 }; @@ -11,20 +12,26 @@ const validate: (level: number) => boolean = (level) => { export const action: objectInteractionActionHandler = (details) => { const { player, option } = details; + + const ladderObjectName = details.objectConfig.name || ''; + if (!ladderObjectName) { + logger.warn(`Ladder object ${details.object.objectId} has no name.`); + } + if (option === 'climb') { dialogueAction(player) .then(async d => d.options( - `Climb up or down the ${details.objectConfig.name.toLowerCase()}?`, + `Climb up or down the ${ladderObjectName.toLowerCase()}?`, [ - `Climb up the ${details.objectConfig.name.toLowerCase()}.`, - `Climb down the ${details.objectConfig.name.toLowerCase()}.` + `Climb up the ${ladderObjectName.toLowerCase()}.`, + `Climb down the ${ladderObjectName.toLowerCase()}.` ])) .then(d => { d.close(); - switch (d._action.data) { + switch (d.action) { case 1: case 2: - action({ ...details, option: `climb-${(d._action.data === 1 ? 'up' : 'down')}` }); + action({ ...details, option: `climb-${(d.action === 1 ? 'up' : 'down')}` }); return; } }); @@ -46,10 +53,10 @@ export const action: objectInteractionActionHandler = (details) => { } } if (!validate(newPosition.level)) return; - if (!details.objectConfig.name.startsWith('Stair')) { + if (!ladderObjectName.startsWith('Stair')) { player.playAnimation(up ? 828 : 827); } - player.sendMessage(`You climb ${option.slice(6)} the ${details.objectConfig.name.toLowerCase()}.`); + player.sendMessage(`You climb ${option.slice(6)} the ${ladderObjectName.toLowerCase()}.`); setTimeout(() => details.player.teleport(newPosition), World.TICK_LENGTH); }; diff --git a/src/plugins/objects/mill/flour-bin.plugin.ts b/src/plugins/objects/mill/flour-bin.plugin.ts index d70361c5e..392f7b533 100644 --- a/src/plugins/objects/mill/flour-bin.plugin.ts +++ b/src/plugins/objects/mill/flour-bin.plugin.ts @@ -1,17 +1,17 @@ import { itemIds } from '@engine/world/config/item-ids'; -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { soundIds } from '@engine/world/config/sound-ids'; -import { itemOnObjectActionHandler } from '@engine/world/action/item-on-object.action'; +import { itemOnObjectActionHandler } from '@engine/action'; import { Player } from '@engine/world/actor/player/player'; import { ObjectConfig } from '@runejs/filestore'; -import { playerInitActionHandler } from '@engine/world/action/player-init.action'; +import { playerInitActionHandler } from '@engine/action'; function flourBin(details: { objectConfig: ObjectConfig, player: Player }): void { const { player, objectConfig } = details; if (!details.player.savedMetadata['mill-flour']) { - player.sendMessage(`The ${objectConfig.name.toLowerCase()} is already empty. You need to place wheat in the hopper upstairs `); + player.sendMessage(`The ${(objectConfig.name || '').toLowerCase()} is already empty. You need to place wheat in the hopper upstairs `); player.sendMessage(`first.`); } else { if (player.hasItemInInventory(itemIds.pot)) { diff --git a/src/plugins/objects/mill/hopper-controls.plugin.ts b/src/plugins/objects/mill/hopper-controls.plugin.ts index 6f19752d8..a923885ea 100644 --- a/src/plugins/objects/mill/hopper-controls.plugin.ts +++ b/src/plugins/objects/mill/hopper-controls.plugin.ts @@ -1,4 +1,4 @@ -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { World } from '@engine/world'; diff --git a/src/plugins/objects/mill/hopper.plugin.ts b/src/plugins/objects/mill/hopper.plugin.ts index 899b88b95..03931d646 100644 --- a/src/plugins/objects/mill/hopper.plugin.ts +++ b/src/plugins/objects/mill/hopper.plugin.ts @@ -1,6 +1,6 @@ import { World } from '@engine/world'; import { itemIds } from '@engine/world/config/item-ids'; -import { itemOnObjectActionHandler } from '@engine/world/action/item-on-object.action'; +import { itemOnObjectActionHandler } from '@engine/action'; export const action: itemOnObjectActionHandler = (details) => { diff --git a/src/plugins/objects/pickables/pickables.plugin.ts b/src/plugins/objects/pickables/pickables.plugin.ts index 8388f034e..2333fc2ca 100644 --- a/src/plugins/objects/pickables/pickables.plugin.ts +++ b/src/plugins/objects/pickables/pickables.plugin.ts @@ -1,7 +1,8 @@ -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { World } from '@engine/world'; import { itemIds } from '@engine/world/config/item-ids'; -import { findItem } from '@engine/config'; +import { findItem } from '@engine/config/config-handler'; +import { logger } from '@runejs/common'; export const action: objectInteractionActionHandler = (details) => { @@ -30,8 +31,15 @@ export const action: objectInteractionActionHandler = (details) => { break; } const pickedItem = findItem(itemId); + + if (!pickedItem) { + logger.warn(`Could not find item for pickable with id ${itemId}`); + details.player.busy = false; + return; + } + setTimeout(() => { - details.player.sendMessage(`You ${details.option} the ${details.objectConfig.name.toLowerCase()} and receive ${prefix} ${pickedItem.name.toLowerCase()}.`); + details.player.sendMessage(`You ${details.option} the ${(details.objectConfig.name || '').toLowerCase()} and receive ${prefix} ${pickedItem.name.toLowerCase()}.`); details.player.playSound(2581, 7); if (details.objectConfig.name !== 'Flax' || Math.floor(Math.random() * 10) === 1) { details.player.instance.hideGameObjectTemporarily(details.object, 30); diff --git a/src/plugins/player/login-unlock-emotes.plugin.ts b/src/plugins/player/login-unlock-emotes.plugin.ts index ff63b4068..d8901969c 100644 --- a/src/plugins/player/login-unlock-emotes.plugin.ts +++ b/src/plugins/player/login-unlock-emotes.plugin.ts @@ -1,5 +1,5 @@ import { unlockEmotes } from '@plugins/buttons/player-emotes.plugin'; -import { playerInitActionHandler } from '@engine/world/action/player-init.action'; +import { playerInitActionHandler } from '@engine/action'; export const handler: playerInitActionHandler = diff --git a/src/plugins/player/login-update-settings.plugin.ts b/src/plugins/player/login-update-settings.plugin.ts index b1d1b0a6d..95074ccfc 100644 --- a/src/plugins/player/login-update-settings.plugin.ts +++ b/src/plugins/player/login-update-settings.plugin.ts @@ -1,6 +1,6 @@ import { validateSettings } from '@engine/world/actor/player/player-data'; import { widgetScripts } from '@engine/world/config/widget'; -import { playerInitActionHandler } from '@engine/world/action/player-init.action'; +import { playerInitActionHandler } from '@engine/action'; export const handler: playerInitActionHandler = ({ player }) => { diff --git a/src/plugins/player/trading.plugin.ts b/src/plugins/player/trading.plugin.ts new file mode 100644 index 000000000..8cc87e045 --- /dev/null +++ b/src/plugins/player/trading.plugin.ts @@ -0,0 +1,102 @@ +import { playerInteractionActionHandler } from '@engine/world/action/player-interaction.action'; +import { widgets } from '@engine/config'; +import { ItemInteractionAction, itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { buttonActionHandler } from '@engine/world/action/button.action'; +import { TradeSession } from '@plugins/player/trading/TradeSession'; +import { Player } from '@engine/world/actor/player/player'; +import { WidgetClosedEvent } from '@engine/world/actor/player/interface-state'; + +/* + Trade Interface 335 + Trading confirmation 334 + Trading tab area 336 + */ +export const trade : playerInteractionActionHandler = ({ player, otherPlayer }) => { + + const currentTime = Date.now(); + + if(otherPlayer.metadata['currentTrade']) { + player.sendMessage('Other player is busy at the moment. (trading atm)') + otherPlayer.metadata['currentTrade'] = null; + return; + } + if(otherPlayer.interfaceState.screenWidget) { + player.sendMessage('Other player is busy at the moment.') + return; + } + + if(player.metadata['tradeRequests']) { + const playerRequests = player.metadata['tradeRequests']; + if(playerRequests[otherPlayer.username] && playerRequests[otherPlayer.username] + 10000 > currentTime) { + player.sendMessage('starting trade'); + otherPlayer.sendMessage('starting trade'); + // Both parties have agreed to start a trade session; + new TradeSession(player, otherPlayer); + return; + } + } + + if(!otherPlayer.metadata['tradeRequests']) { + otherPlayer.metadata['tradeRequests'] = {}; + } + + otherPlayer.metadata['tradeRequests'][player.username] = Date.now(); + otherPlayer.sendMessage(`${player.username}:tradereq:`); + player.sendMessage(`Sending trade request...`); +}; + +export const offerItemToTrade : itemInteractionActionHandler = (itemInteractionAction: ItemInteractionAction) => { + console.log('Offering item to trade: '); + console.log('Username: ', itemInteractionAction.player.username); + console.log('Item: ', itemInteractionAction.itemDetails.name); + console.log('Option: ', itemInteractionAction.option); + + const { player } = itemInteractionAction; + + const tradingSession = player.metadata['currentTrade']; + if(!tradingSession) { + return; + } + + tradingSession.addItem(player, itemInteractionAction, 1); +} + + +const removeItemFromTrade : itemInteractionActionHandler = (itemInteractionAction) => { + console.log('Removing item from trade: '); + console.log('Username: ', itemInteractionAction.player.username); + console.log('Item: ', itemInteractionAction.itemDetails.name); + console.log('Option: ', itemInteractionAction.option); + + const { player } = itemInteractionAction; + const tradingSession = player.metadata['currentTrade']; + + tradingSession.removeItem(player, itemInteractionAction, 1); + +} + +export default { + pluginId: 'rs:trading', + hooks: [ + { + options: 'trade with', + type: 'player_interaction', + handler: trade + }, + { + options: 'request_response', + type: 'player_interaction', + handler: trade + }, + { + options: ['offer-1', 'offer-5', 'offer-10', 'offer-all'], + type: 'item_interaction', + handler: offerItemToTrade + }, + { + options: ['remove-1', 'remove-5', 'remove-10', 'remove-all'], + type: 'item_interaction', + handler: removeItemFromTrade + } + ] +} diff --git a/src/plugins/player/trading/TradeSession.ts b/src/plugins/player/trading/TradeSession.ts new file mode 100644 index 000000000..60bb61f89 --- /dev/null +++ b/src/plugins/player/trading/TradeSession.ts @@ -0,0 +1,185 @@ +import { Player } from '@engine/world/actor/player/player'; +import { ItemContainer } from '@engine/world/items/item-container'; +import { widgets } from '@engine/config'; +import { WidgetClosedEvent } from '@engine/world/actor/player/interface-state'; +import { ItemInteractionAction } from '@engine/world/action/item-interaction.action'; + +enum TradingStage { + Initializing, + Offer, + Confirm +} + +export class TradeSession { + + private player1: Player; + private player2: Player; + + private player1ActiveWidget; + private player2ActiveWidget; + + private player1Offer: ItemContainer = new ItemContainer(28); + private player2Offer: ItemContainer = new ItemContainer(28); + + private tradingStage: TradingStage = TradingStage.Initializing; + + constructor(player1: Player, player2: Player) { + this.player1 = player1; + this.player2 = player2; + player1.metadata['currentTrade'] = this; + player2.metadata['currentTrade'] = this; + this.openWidgets(); + this.tradingStage = TradingStage.Offer; + + this.player1ActiveWidget = player1.interfaceState.closed.subscribe((whatClosed: WidgetClosedEvent) => { + if (whatClosed.widget.widgetId === 335 || whatClosed.widget.widgetId === 334) { + this.abort(); + } + }); + + this.player2ActiveWidget = player2.interfaceState.closed.subscribe((whatClosed: WidgetClosedEvent) => { + if (whatClosed.widget.widgetId === 335 || whatClosed.widget.widgetId === 334) { + this.abort(); + } + }); + } + + public reloadPlayerWidgets() { + this.player1.outgoingPackets.sendUpdateAllWidgetItems(widgets.trading.tabarea, this.player1.inventory); + this.player2.outgoingPackets.sendUpdateAllWidgetItems(widgets.trading.tabarea, this.player2.inventory); + + this.player2.outgoingPackets.sendUpdateAllWidgetItems({ + widgetId: widgets.trading.firstStage.widgetId, + containerId: widgets.trading.firstStage.source.containerId + }, this.player2Offer); + + this.player2.outgoingPackets.sendUpdateAllWidgetItems({ + widgetId: widgets.trading.firstStage.widgetId, + containerId: widgets.trading.firstStage.target.containerId + }, this.player1Offer); + + this.player1.outgoingPackets.sendUpdateAllWidgetItems({ + widgetId: widgets.trading.firstStage.widgetId, + containerId: widgets.trading.firstStage.source.containerId + }, this.player1Offer); + + this.player1.outgoingPackets.sendUpdateAllWidgetItems({ + widgetId: widgets.trading.firstStage.widgetId, + containerId: widgets.trading.firstStage.target.containerId + }, this.player2Offer); + } + + /** + * Add an item to the trade offer. + * @param player + * @param itemInteractionAction + * @param amount + * @private + */ + public addItem(player: Player, itemInteractionAction: ItemInteractionAction, amount: number) { + const tradingSession = player.metadata['currentTrade']; + + if(player.username === this.player1.username) { + this.player1Offer.add({ itemId: itemInteractionAction.itemId, amount: amount }); + this.player1.inventory.remove(itemInteractionAction.itemSlot); + tradingSession.reloadPlayerWidgets(); + } + + if(player.username === this.player2.username) { + this.player2Offer.add({ itemId: itemInteractionAction.itemId, amount: amount }); + this.player2.inventory.remove(itemInteractionAction.itemSlot); + tradingSession.reloadPlayerWidgets(); + } + } + + /** + * Remove an item from the trade offer. + * @param player + * @param itemInteractionAction + * @param amount + * @private + */ + public removeItem(player: Player, itemInteractionAction: ItemInteractionAction, amount: number) { + const tradingSession = player.metadata['currentTrade']; + + if(player.username === this.player1.username) { + this.player1Offer.remove(itemInteractionAction.itemSlot); + this.player1.inventory.add({ itemId: itemInteractionAction.itemId, amount: amount }); + tradingSession.reloadPlayerWidgets(); + } + + if(player.username === this.player2.username) { + this.player2Offer.remove(itemInteractionAction.itemSlot); + this.player2.inventory.add({ itemId: itemInteractionAction.itemId, amount: amount }); + tradingSession.reloadPlayerWidgets(); + } + } + + /** + * Open the trading widgets for both players. + * @private + */ + public openWidgets() { + // Open trading interface on target players screen. + this.player1.interfaceState.openWidget(335, { + slot: 'screen', + multi: true + }); + + this.player1.interfaceState.openWidget(336, { + slot: 'tabarea', + multi: true + }); + + this.player1.modifyWidget(widgets.trading.firstStage.widgetId, { + childId: widgets.trading.firstStage.titleId, + text: 'Trading With: ' + this.player2.username + }); + + this.player1.interfaceState.openWidget(336, { + slot: 'tabarea', + multi: true, + }); + + // Open trading interface on source player screen. + this.player2.interfaceState.openWidget(335, { + slot: 'screen', + multi: true, + }); + + this.player2.modifyWidget(widgets.trading.firstStage.widgetId, { + childId: widgets.trading.firstStage.titleId, + text: 'Trading With: ' + this.player1.username + }); + + this.player2.interfaceState.openWidget(336, { + slot: 'tabarea', + multi: true + }); + + this.reloadPlayerWidgets(); + } + + public abort() { + // Unsubscribe active widgets. + this.player1ActiveWidget.unsubscribe(); + this.player2ActiveWidget.unsubscribe(); + + // @todo: Put the items back into the right inventories. + /* for(let i1 = 0; i1 < this.player1Offer.size; i1++) { + this.player1.inventory.add(this.player1Offer[i1]); + } + for (let i2 = 0; i2 < this.player2Offer.size; i2++) { + this.player2.inventory.add(this.player2Offer[i2]); + } */ + + // Close all widgets. + this.player1.interfaceState.closeAllSlots(); + this.player2.interfaceState.closeAllSlots(); + + // Reset the 'current trade' metadata. + this.player1.metadata['currentTrade'] = null; + this.player2.metadata['currentTrade'] = null; + } + +} diff --git a/src/plugins/player/update-friends-list.plugin.ts b/src/plugins/player/update-friends-list.plugin.ts index 47ade12b8..ac851a27d 100644 --- a/src/plugins/player/update-friends-list.plugin.ts +++ b/src/plugins/player/update-friends-list.plugin.ts @@ -1,5 +1,5 @@ import { PrivateMessaging } from '@engine/world/actor/player/private-messaging'; -import { playerInitActionHandler } from '@engine/world/action/player-init.action'; +import { playerInitActionHandler } from '@engine/action'; export const handler: playerInitActionHandler = ({ player }) => { diff --git a/src/plugins/quests/cooks-assistant-quest.plugin.ts b/src/plugins/quests/cooks-assistant-quest.plugin.ts index ec01cef88..46fcc1441 100644 --- a/src/plugins/quests/cooks-assistant-quest.plugin.ts +++ b/src/plugins/quests/cooks-assistant-quest.plugin.ts @@ -1,4 +1,4 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action'; import { dialogue, DialogueTree, Emote, execute, goto } from '@engine/world/actor/dialogue'; import { itemIds } from '@engine/world/config/item-ids'; import { PlayerQuest, QuestJournalHandler } from '@engine/config/quest-config'; diff --git a/src/plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin.ts b/src/plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin.ts index b839815b4..35f8976bf 100644 --- a/src/plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin.ts +++ b/src/plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin.ts @@ -1,23 +1,24 @@ import { defaultPlayerTabWidgets, Player } from '@engine/world/actor/player/player'; import { questDialogueActionFactory, QuestJournalHandler } from '@engine/config/quest-config'; -import { serverConfig, world } from '@engine/game-server'; +import { serverConfig } from '@server/game/game-server'; import uuidv4 from 'uuid/v4'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; import { Position } from '@engine/world/position'; import { WorldInstance } from '@engine/world/instances'; -import { findNpc, widgets } from '@engine/config'; +import { findNpc, widgets } from '@engine/config/config-handler'; import { updateCombatStyleWidget } from '@plugins/combat/combat-styles.plugin'; import { Subject } from 'rxjs'; import { dialogue } from '@engine/world/actor/dialogue'; import { take } from 'rxjs/operators'; -import { equipmentChangeActionHandler } from '@engine/world/action/equipment-change.action'; -import { buttonActionHandler } from '@engine/world/action/button.action'; -import { tabIndex } from '@engine/world/actor/player/interface-state'; +import { equipmentChangeActionHandler } from '@engine/action'; +import { buttonActionHandler } from '@engine/action'; +import { tabIndex } from '@engine/interface'; import { runescapeGuideDialogueHandler } from './runescape-guide-dialogue'; import { harlanDialogueHandler } from './melee-tutor-dialogue'; import { goblinDiplomacyStageHandler } from './stage-handler'; import { Quest } from '@engine/world/actor/player/quest'; -import { playerInitActionHandler } from '@engine/world/action/player-init.action'; +import { playerInitActionHandler } from '@engine/action'; +import { activeWorld } from '@engine/world'; export const tutorialTabWidgetOrder = [ @@ -34,10 +35,11 @@ export const tutorialTabWidgetOrder = [ ]; export function showTabWidgetHint(player: Player, tabIndex: number, availableTabs: number, finalProgress: number, helpTitle: string, helpText: string): void { - player.metadata.tabClickEvent = { + const tabClickEvent = { tabIndex, event: new Subject() }; + player.metadata.tabClickEvent = tabClickEvent; dialogue([ player ], [ titled => [ helpTitle, helpText ] @@ -48,11 +50,11 @@ export function showTabWidgetHint(player: Player, tabIndex: number, availableTab unlockAvailableTabs(player, availableTabs); player.outgoingPackets.blinkTabIcon(tabIndex); - player.metadata.tabClickEvent.event.pipe(take(1)).subscribe(async () => { + tabClickEvent.event.pipe(take(1)).subscribe(async () => { player.setQuestProgress('tyn:goblin_diplomacy', finalProgress); - player.metadata.tabClickEvent.event.complete(); + tabClickEvent.event.complete(); delete player.metadata.tabClickEvent; - await handleTutorial(player); + await tutorialHandler(player); }); } @@ -85,7 +87,7 @@ export function npcHint(player: Player, npcKey: string | number): void { npcKey = npc.gameId; } - const npc = world.findNpcsById(npcKey as number, player.instance.instanceId)[0] || null; + const npc = activeWorld.findNpcsById(npcKey as number, player.instance.instanceId)[0] || null; if(npc) { player.outgoingPackets.showNpcHintIcon(npc); @@ -95,7 +97,7 @@ export function npcHint(player: Player, npcKey: string | number): void { export const startTutorial = async (player: Player): Promise => { player.setQuestProgress('tyn:goblin_diplomacy', 0); - defaultPlayerTabWidgets.forEach((widgetId: number, tabIndex: number) => { + defaultPlayerTabWidgets().forEach((widgetId: number, tabIndex: number) => { if(widgetId !== -1) { player.outgoingPackets.sendTabWidget(tabIndex, widgetId === widgets.logoutTab ? widgetId : null); } @@ -123,7 +125,7 @@ export const startTutorial = async (player: Player): Promise => { }; export async function spawnGoblinBoi(player: Player, spawnPoint: 'beginning' | 'end'): Promise { - const nearbyGoblins = world.findNpcsByKey('rs:goblin', player.instance.instanceId); + const nearbyGoblins = activeWorld.findNpcsByKey('rs:goblin', player.instance.instanceId); if(nearbyGoblins && nearbyGoblins.length > 0) { // Goblin is already spawned, do nothing return; @@ -133,7 +135,7 @@ export async function spawnGoblinBoi(player: Player, spawnPoint: 'beginning' | ' if(spawnPoint === 'beginning') { //const goblin = await world.spawnNpc('rs:goblin', new Position(3219, 3246), 'SOUTH', // 0, player.instance.instanceId); - const goblin = await world.spawnNpc('rs:goblin', new Position(3221, 3257), 'SOUTH', + const goblin = await activeWorld.spawnNpc('rs:goblin', new Position(3221, 3257), 'SOUTH', 0, player.instance.instanceId); goblin.pathfinding.walkTo(new Position(3219, 3246), { @@ -141,16 +143,16 @@ export async function spawnGoblinBoi(player: Player, spawnPoint: 'beginning' | ' ignoreDestination: false }); } else { - await world.spawnNpc('rs:goblin', new Position(3219, 3246), 'SOUTH', + await activeWorld.spawnNpc('rs:goblin', new Position(3219, 3246), 'SOUTH', 0, player.instance.instanceId); } } -export async function handleTutorial(player: Player): Promise { +export async function tutorialHandler(player: Player): Promise { const progress = player.getQuest('tyn:goblin_diplomacy').progress; const handler = goblinDiplomacyStageHandler[progress]; - defaultPlayerTabWidgets.forEach((widgetId: number, tabIndex: number) => { + defaultPlayerTabWidgets().forEach((widgetId: number, tabIndex: number) => { if(widgetId !== -1) { player.setSidebarWidget(tabIndex, widgetId === widgets.logoutTab ? widgetId : null); } @@ -163,8 +165,8 @@ export async function handleTutorial(player: Player): Promise { } function spawnQuestNpcs(player: Player): void { - world.spawnNpc('rs:runescape_guide', new Position(3230, 3238), 'SOUTH', 2, player.instance.instanceId); - world.spawnNpc('rs:melee_combat_tutor', new Position(3219, 3238), 'EAST', 1, player.instance.instanceId); + activeWorld.spawnNpc('rs:runescape_guide', new Position(3230, 3238), 'SOUTH', 2, player.instance.instanceId); + activeWorld.spawnNpc('rs:melee_combat_tutor', new Position(3219, 3238), 'EAST', 1, player.instance.instanceId); } const tutorialInitAction: playerInitActionHandler = async ({ player }) => { @@ -172,9 +174,9 @@ const tutorialInitAction: playerInitActionHandler = async ({ player }) => { player.instance = new WorldInstance(uuidv4()); player.metadata.blockObjectInteractions = true; spawnQuestNpcs(player); - await handleTutorial(player); + await tutorialHandler(player); } else { - defaultPlayerTabWidgets.forEach((widgetId: number, tabIndex: number) => { + defaultPlayerTabWidgets().forEach((widgetId: number, tabIndex: number) => { if(widgetId !== -1) { player.setSidebarWidget(tabIndex, widgetId); } @@ -192,7 +194,7 @@ const trainingSwordEquipAction: equipmentChangeActionHandler = async ({ player, if((itemDetails.key === 'rs:training_sword' && shieldEquipped) || (itemDetails.key === 'rs:training_shield' && swordEquipped)) { player.setQuestProgress('tyn:goblin_diplomacy', 90); - await handleTutorial(player); + await tutorialHandler(player); } } }; @@ -208,29 +210,32 @@ const journalHandler: QuestJournalHandler = { }; +const QUEST_ID = 'tyn:goblin_diplomacy'; + +const QUEST = new Quest({ + id: QUEST_ID, + questTabId: 28, + name: `Goblin Diplomacy`, + points: 1, + journalHandler, + onComplete: { + questCompleteWidget: { + rewardText: [ 'A training sword & shield' ], + itemId: 9703, + modelZoom: 200, + modelRotationX: 0, + modelRotationY: 180 + } + } +}); + + /** * Custom Goblin Diplomacy tutorial quest! */ export default { pluginId: 'tyn:goblin_diplomacy_quest', - quests: [ - new Quest({ - id: 'tyn:goblin_diplomacy', - questTabId: 28, - name: `Goblin Diplomacy`, - points: 1, - journalHandler, - onComplete: { - questCompleteWidget: { - rewardText: [ 'A training sword & shield' ], - itemId: 9703, - modelZoom: 200, - modelRotationX: 0, - modelRotationY: 180 - } - } - }) - ], + quests: [ QUEST ], hooks: [ { type: 'player_init', @@ -238,14 +243,14 @@ export default { }, { type: 'npc_interaction', - handler: questDialogueActionFactory('tyn:goblin_diplomacy', runescapeGuideDialogueHandler), + handler: questDialogueActionFactory(QUEST_ID, runescapeGuideDialogueHandler, tutorialHandler), npcs: 'rs:runescape_guide', options: 'talk-to', walkTo: true }, { type: 'npc_interaction', - handler: questDialogueActionFactory('tyn:goblin_diplomacy', harlanDialogueHandler), + handler: questDialogueActionFactory(QUEST_ID, harlanDialogueHandler, tutorialHandler), npcs: 'rs:melee_combat_tutor', options: 'talk-to', walkTo: true diff --git a/src/plugins/quests/goblin-diplomacy-tutorial/runescape-guide-dialogue.ts b/src/plugins/quests/goblin-diplomacy-tutorial/runescape-guide-dialogue.ts index 3067110d8..5d5800884 100644 --- a/src/plugins/quests/goblin-diplomacy-tutorial/runescape-guide-dialogue.ts +++ b/src/plugins/quests/goblin-diplomacy-tutorial/runescape-guide-dialogue.ts @@ -27,7 +27,7 @@ export const runescapeGuideDialogueHandler: QuestDialogueHandler = { player.savedMetadata.tutorialComplete = true; player.setQuestProgress('tyn:goblin_diplomacy', 'complete'); player.instance = null; - defaultPlayerTabWidgets.forEach((widgetId: number, tabIndex: number) => { + defaultPlayerTabWidgets().forEach((widgetId: number, tabIndex: number) => { if(widgetId !== -1) { player.setSidebarWidget(tabIndex, widgetId); } diff --git a/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts b/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts index 90b145d4e..d69d06d80 100644 --- a/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts +++ b/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts @@ -1,23 +1,24 @@ import { dialogue } from '@engine/world/actor/dialogue'; import { - handleTutorial, + tutorialHandler, npcHint, showTabWidgetHint, spawnGoblinBoi, startTutorial, unlockAvailableTabs } from '@plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy-quest.plugin'; import { schedule } from '@engine/world/task'; -import { world } from '@engine/game-server'; -import { findNpc } from '@engine/config'; +import { findNpc } from '@engine/config/config-handler'; import { Cutscene } from '@engine/world/actor/player/cutscenes'; import { soundIds } from '@engine/world/config/sound-ids'; import { QuestStageHandler } from '@engine/config/quest-config'; -import { tabIndex } from '@engine/world/actor/player/interface-state'; +import { tabIndex } from '@engine/interface'; +import { activeWorld } from '@engine/world'; +import { logger } from '@runejs/common'; export const goblinDiplomacyStageHandler: QuestStageHandler = { 0: async player => { await startTutorial(player); player.setQuestProgress('tyn:goblin_diplomacy', 5); - await handleTutorial(player); + await tutorialHandler(player); }, 5: async player => { npcHint(player, 'rs:runescape_guide'); @@ -187,12 +188,37 @@ export const goblinDiplomacyStageHandler: QuestStageHandler = { await schedule(3); - const goblinDetails = findNpc('rs:goblin'); - let anim = goblinDetails.combatAnimations.attack; - if(Array.isArray(anim)) { - anim = anim[0]; + function getAnim() { + const goblinDetails = findNpc('rs:goblin'); + + if (!goblinDetails) { + logger.error('Could not find goblin details.'); + return null; + } + + const anims = goblinDetails.combatAnimations; + + if (!anims) { + return null; + } + + if (!anims.attack) { + return null; + } + + if (Array.isArray(anims.attack)) { + return anims.attack[0]; + } + + return anims.attack; } - world.findNpcsByKey('rs:goblin', player.instance.instanceId)[0].playAnimation(anim); + + const goblinAnim = getAnim(); + + if (goblinAnim !== null) { + activeWorld.findNpcsByKey('rs:goblin', player.instance.instanceId)[0].playAnimation(goblinAnim); + } + player.playSound(soundIds.npc.human.maleDefence, 5); } }; diff --git a/src/plugins/quests/quest-journal.plugin.ts b/src/plugins/quests/quest-journal.plugin.ts index 358be7443..28183b475 100644 --- a/src/plugins/quests/quest-journal.plugin.ts +++ b/src/plugins/quests/quest-journal.plugin.ts @@ -1,9 +1,9 @@ -import { buttonActionHandler } from '@engine/world/action/button.action'; +import { buttonActionHandler } from '@engine/action'; import { wrapText } from '@engine/util/strings'; -import { questMap } from '@engine/game-server'; -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; import { Quest } from '@engine/world/actor/player/quest'; import { QuestKey } from '@engine/config/quest-config'; +import { questMap } from '@engine/plugins'; export const handler: buttonActionHandler = async ({ player, buttonId }) => { @@ -41,7 +41,7 @@ export const handler: buttonActionHandler = async ({ player, buttonId }) => { } const color = 128; - let text: string; + let text: string = ''; if(typeof journalHandler === 'function') { text = await Promise.resolve(journalHandler(player)); @@ -49,7 +49,7 @@ export const handler: buttonActionHandler = async ({ player, buttonId }) => { text = journalHandler; } - let lines; + let lines: string[]; if(text) { lines = wrapText(text as string, 395); } else { diff --git a/src/plugins/quests/witchs-potion-quest.plugin.ts b/src/plugins/quests/witchs-potion-quest.plugin.ts index 430e3043e..1b5672617 100644 --- a/src/plugins/quests/witchs-potion-quest.plugin.ts +++ b/src/plugins/quests/witchs-potion-quest.plugin.ts @@ -1,10 +1,10 @@ -import { npcInteractionActionHandler } from '@engine/world/action/npc-interaction.action'; +import { npcInteractionActionHandler } from '@engine/action/pipe/npc-interaction.action'; import { dialogue, DialogueTree, Emote, execute, goto } from '@engine/world/actor/dialogue'; import { itemIds } from '@engine/world/config/item-ids'; import { QuestJournalHandler } from '@engine/config/quest-config'; import { Player } from '@engine/world/actor/player/player'; import { Quest } from '@engine/world/actor/player/quest'; -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action/pipe/object-interaction.action'; import { Position } from '@engine/world/position'; diff --git a/src/plugins/skills/construction/home-saver.ts b/src/plugins/skills/construction/home-saver.ts index 336e58ebd..f9ae957c2 100644 --- a/src/plugins/skills/construction/home-saver.ts +++ b/src/plugins/skills/construction/home-saver.ts @@ -2,7 +2,7 @@ import { Player } from '@engine/world/actor/player/player'; import { ConstructedRegion } from '@engine/world/map/region'; import JSON5 from 'json5'; import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; -import { logger } from '@runejs/core'; +import { logger } from '@runejs/common'; import { join } from 'path'; import { House, Room } from '@plugins/skills/construction/house'; diff --git a/src/plugins/skills/construction/house.ts b/src/plugins/skills/construction/house.ts index cdc88c15b..5c25c07e0 100644 --- a/src/plugins/skills/construction/house.ts +++ b/src/plugins/skills/construction/house.ts @@ -6,8 +6,8 @@ import { import { Position } from '@engine/world/position'; import { ConstructedChunk, ConstructedRegion } from '@engine/world/map/region'; import { Player } from '@engine/world/actor/player/player'; -import { world } from '@engine/game-server'; import { loadHouse } from '@plugins/skills/construction/home-saver'; +import { activeWorld } from '@engine/world'; export const openHouse = (player: Player): void => { @@ -55,7 +55,7 @@ export const openHouse = (player: Player): void => { const templatePosition = room.templatePosition; // load all the PoH template maps into memory so that their collision maps are generated - world.chunkManager.getChunk(templatePosition); + activeWorld.chunkManager.getChunk(templatePosition); } } } @@ -66,7 +66,7 @@ export const openHouse = (player: Player): void => { export class House { - public rooms: Room[][][]; + public rooms: (Room | null)[][][]; public constructor() { this.rooms = new Array(4); @@ -84,11 +84,12 @@ export class House { } } - public copyRooms(rooms: Room[][][]): void { + public copyRooms(rooms: (Room | null)[][][]): void { for(let level = 0; level < 4; level++) { for(let x = 0; x < MAP_SIZE; x++) { for(let y = 0; y < MAP_SIZE; y++) { const existingRoom = rooms[level][x][y] ?? null; + this.rooms[level][x][y] = existingRoom ? new Room(existingRoom.type, existingRoom.orientation) : null; } } diff --git a/src/plugins/skills/construction/index.ts b/src/plugins/skills/construction/index.ts index 3fd9ec229..79f544860 100644 --- a/src/plugins/skills/construction/index.ts +++ b/src/plugins/skills/construction/index.ts @@ -1,5 +1,5 @@ -import { PlayerCommandAction } from '@engine/world/action/player-command.action'; -import { PlayerInitAction } from '@engine/world/action/player-init.action'; +import { PlayerCommandAction } from '@engine/action'; +import { PlayerInitAction } from '@engine/action'; import { instance1, instance1Max, instance2, instance2Max, roomBuilderButtonMap } from './con-constants'; import { doorHotspotHandler, roomBuilderWidgetHandler } from '@plugins/skills/construction/room-builder'; import { openHouse } from '@plugins/skills/construction/house'; diff --git a/src/plugins/skills/construction/room-builder.ts b/src/plugins/skills/construction/room-builder.ts index 8a4b1a131..ade1d08d9 100644 --- a/src/plugins/skills/construction/room-builder.ts +++ b/src/plugins/skills/construction/room-builder.ts @@ -1,13 +1,14 @@ import { objectInteractionActionHandler -} from '@engine/world/action/object-interaction.action'; +} from '@engine/action/pipe/object-interaction.action'; import { openHouse, Room } from '@plugins/skills/construction/house'; import { MAP_SIZE, roomBuilderButtonMap } from '@plugins/skills/construction/con-constants'; -import { buttonActionHandler } from '@engine/world/action/button.action'; +import { buttonActionHandler } from '@engine/action/pipe/button.action'; import { getCurrentRoom } from '@plugins/skills/construction/util'; import { Player } from '@engine/world/actor/player/player'; import { Coords } from '@engine/world/position'; import { dialogue, execute, goto } from '@engine/world/actor/dialogue'; +import { logger } from '@runejs/common'; const newRoomOriention = (player: Player): number => { @@ -87,7 +88,12 @@ export const canBuildNewRoom = (player: Player): Coords | null => { return null; } - const rooms = player.metadata.customMap.chunks as Room[][][]; + const playerCustomMap = player.metadata.customMap; + if(!playerCustomMap) { + logger.error(`Player ${player.username} does not have a custom map.`); + return null; + } + const rooms = playerCustomMap.chunks as Room[][][]; const existingRoom = rooms[player.position.level][buildX][buildY]; if(existingRoom && existingRoom.type !== 'empty_grass' && existingRoom.type !== 'empty') { @@ -114,8 +120,14 @@ export const roomBuilderWidgetHandler: buttonActionHandler = async ({ player, bu return; } + const playerCustomMap = player.metadata.customMap; + if(!playerCustomMap) { + logger.error(`Player ${player.username} does not have a custom map.`); + return; + } + const createdRoom = new Room(chosenRoomType, newRoomOriention(player)); - player.metadata.customMap.chunks[newRoomCoords.level][newRoomCoords.x][newRoomCoords.y] = createdRoom; + playerCustomMap.chunks[newRoomCoords.level][newRoomCoords.x][newRoomCoords.y] = createdRoom; player.interfaceState.closeAllSlots(); diff --git a/src/plugins/skills/construction/util.ts b/src/plugins/skills/construction/util.ts index b23a91e38..6cca31f99 100644 --- a/src/plugins/skills/construction/util.ts +++ b/src/plugins/skills/construction/util.ts @@ -1,7 +1,6 @@ import { Player } from '@engine/world/actor/player/player'; import { Coords, Position } from '@engine/world/position'; -import { world } from '@engine/game-server'; -import { ConstructedRegion } from '@engine/world/map/region'; +import { activeWorld } from '@engine/world'; /** @@ -10,7 +9,7 @@ import { ConstructedRegion } from '@engine/world/map/region'; * @param player The player to find the room for. */ export const getCurrentRoom = (player: Player): Coords | null => { - const customMap: ConstructedRegion = player.metadata?.customMap; + const customMap = player.metadata?.customMap; if(!customMap) { return null; @@ -19,8 +18,8 @@ export const getCurrentRoom = (player: Player): Coords | null => { const mapWorldX = customMap.renderPosition.x; const mapWorldY = customMap.renderPosition.y; - const topCornerMapChunk = world.chunkManager.getChunkForWorldPosition(new Position(mapWorldX, mapWorldY, player.position.level)); - const playerChunk = world.chunkManager.getChunkForWorldPosition(player.position); + const topCornerMapChunk = activeWorld.chunkManager.getChunkForWorldPosition(new Position(mapWorldX, mapWorldY, player.position.level)); + const playerChunk = activeWorld.chunkManager.getChunkForWorldPosition(player.position); const currentRoomX = playerChunk.position.x - (topCornerMapChunk.position.x - 2); const currentRoomY = playerChunk.position.y - (topCornerMapChunk.position.y - 2); diff --git a/src/plugins/skills/crafting/sheep-plugin.plugin.ts b/src/plugins/skills/crafting/sheep-plugin.plugin.ts index c85765cd6..f6d341360 100644 --- a/src/plugins/skills/crafting/sheep-plugin.plugin.ts +++ b/src/plugins/skills/crafting/sheep-plugin.plugin.ts @@ -1,9 +1,9 @@ import { World } from '@engine/world'; -import { itemOnNpcActionHandler } from '@engine/world/action/item-on-npc.action'; +import { itemOnNpcActionHandler } from '@engine/action'; import { itemIds } from '@engine/world/config/item-ids'; import { soundIds } from '@engine/world/config/sound-ids'; import { animationIds } from '@engine/world/config/animation-ids'; -import { npcInitActionHandler } from '@engine/world/action/npc-init.action'; +import { npcInitActionHandler } from '@engine/action'; const initAction: npcInitActionHandler = ({ npc }) => { diff --git a/src/plugins/skills/crafting/spinning-wheel.plugin.ts b/src/plugins/skills/crafting/spinning-wheel.plugin.ts index 3f04ca312..71fc8f77a 100644 --- a/src/plugins/skills/crafting/spinning-wheel.plugin.ts +++ b/src/plugins/skills/crafting/spinning-wheel.plugin.ts @@ -1,12 +1,13 @@ -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; -import { buttonActionHandler, ButtonAction } from '@engine/world/action/button.action'; +import { objectInteractionActionHandler } from '@engine/action'; +import { buttonActionHandler, ButtonAction } from '@engine/action'; import { soundIds } from '@engine/world/config/sound-ids'; import { itemIds } from '@engine/world/config/item-ids'; import { Skill } from '@engine/world/actor/skills'; -import { filestore, loopingEvent } from '@engine/game-server'; import { animationIds } from '@engine/world/config/animation-ids'; import { objectIds } from '@engine/world/config/object-ids'; -import { findItem, widgets } from '@engine/config'; +import { findItem, widgets } from '@engine/config/config-handler'; +import { loopingEvent } from '@engine/plugins'; +import { logger } from '@runejs/common'; interface Spinnable { input: number | number[]; @@ -25,10 +26,10 @@ const ballOfWool: Spinnable = { input: itemIds.wool, output: itemIds.ballOfWool, const bowString: Spinnable = { input: itemIds.flax, output: itemIds.bowstring, experience: 15, requiredLevel: 10 }; const rootsCbowString: Spinnable = { input: [ - itemIds.oakRoots, - itemIds.willowRoots, - itemIds.mapleRoots, - itemIds.yewRoots + itemIds.roots.oak, + itemIds.roots.willow, + itemIds.roots.maple, + itemIds.roots.yew ], output: itemIds.crossbowString, experience: 15, @@ -41,7 +42,7 @@ const sinewCbowString: Spinnable = { requiredLevel: 10 }; const magicAmuletString: Spinnable = { - input: itemIds.magicRoots, + input: itemIds.roots.magic, output: itemIds.magicString, experience: 30, requiredLevel: 19 @@ -111,7 +112,8 @@ const spinProduct: any = (details: ButtonAction, spinnable: Spinnable, count: nu cancel = true; } if (cancel) { - details.player.sendMessage(`You don't have any ${findItem(currentItem).name.toLowerCase()}.`); + const itemName = findItem(currentItem)?.name || ''; + details.player.sendMessage(`You don't have any ${itemName.toLowerCase()}.`); loop.cancel(); return; } @@ -140,11 +142,18 @@ export const buttonClicked: buttonActionHandler = (details) => { } const product = widgetButtonIds.get(details.buttonId); + if (!product) { + logger.error(`Unhandled button id ${details.buttonId} for buttonClicked in spinning wheel.`); + return; + } + // Close the widget as it is no longer needed details.player.interfaceState.closeAllSlots(); if (!details.player.skills.hasLevel(Skill.CRAFTING, product.spinnable.requiredLevel)) { - details.player.sendMessage(`You need a crafting level of ${product.spinnable.requiredLevel} to craft ${findItem(product.spinnable.output).name.toLowerCase()}.`, true); + const outputName = findItem(product.spinnable.output)?.name || ''; + + details.player.sendMessage(`You need a crafting level of ${product.spinnable.requiredLevel} to craft ${outputName.toLowerCase()}.`, true); return; } diff --git a/src/plugins/skills/firemaking.plugin.ts b/src/plugins/skills/firemaking.plugin.ts deleted file mode 100644 index 8609cba5d..000000000 --- a/src/plugins/skills/firemaking.plugin.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { itemOnItemActionHandler } from '@engine/world/action/item-on-item.action'; -import { Player } from '@engine/world/actor/player/player'; -import { WorldItem } from '@engine/world/items/world-item'; -import { Position } from '@engine/world/position'; -import { randomBetween } from '@engine/util/num'; -import { objectIds } from '@engine/world/config/object-ids'; -import { itemIds } from '@engine/world/config/item-ids'; -import { soundIds } from '@engine/world/config/sound-ids'; -import { animationIds } from '@engine/world/config/animation-ids'; -import { loopingEvent } from '@engine/game-server'; -import { LandscapeObject } from '@runejs/filestore'; - - -const logs = [ - { - logId: itemIds.logs, - requiredLevel: 1, - burnExp: 40 - } -]; - -const canLight = (logLevel: number, playerLevel: number): boolean => { - playerLevel++; - const hostRatio = Math.random() * logLevel; - const clientRatio = Math.random() * ((playerLevel - logLevel) * (1 + (logLevel * 0.01))); - return hostRatio < clientRatio; -}; - -const canChain = (logLevel: number, playerLevel: number): boolean => { - playerLevel++; - const hostRatio = Math.random() * logLevel; - const clientRatio = Math.random() * ((playerLevel - logLevel) * (1 + (logLevel * 0.01))); - return clientRatio - hostRatio < 3.5; -}; - -const fireDuration = (): number => { - return randomBetween(100, 200); // 1-2 minutes -}; - -const lightFire = (player: Player, position: Position, worldItemLog: WorldItem, burnExp: number): void => { - player.instance.despawnWorldItem(worldItemLog); - const fireObject: LandscapeObject = { - objectId: objectIds.fire, - x: position.x, - y: position.y, - level: position.level, - type: 10, - orientation: 0 - }; - - player.playAnimation(null); - player.sendMessage(`The fire catches and the logs begin to burn.`); - player.skills.firemaking.addExp(burnExp); - - if(!player.walkingQueue.moveIfAble(-1, 0)) { - if(!player.walkingQueue.moveIfAble(1, 0)) { - if(!player.walkingQueue.moveIfAble(0, -1)) { - player.walkingQueue.moveIfAble(0, 1); - } - } - } - - player.instance.spawnTemporaryGameObject(fireObject, position, fireDuration()).then(() => { - player.instance.spawnWorldItem({ itemId: itemIds.ashes, amount: 1 }, position, { expires: 300 }); - }); - - player.face(position, false); - player.metadata.lastFire = Date.now(); - player.metadata.busy = false; -}; - -const action: itemOnItemActionHandler = (details) => { - const { player, usedItem, usedWithItem, usedSlot, usedWithSlot } = details; - - if(player.metadata['lastFire'] && Date.now() - player.metadata['lastFire'] < 600) { - return; - } - - const log = usedItem.itemId !== itemIds.tinderbox ? usedItem : usedWithItem; - const removeFromSlot = usedItem.itemId !== itemIds.tinderbox ? usedSlot : usedWithSlot; - const skillInfo = logs.find(l => l.logId === log.itemId); - const position = player.position; - - if(!skillInfo) { - player.sendMessage(`Mishandled firemaking log ${log.itemId}.`); - return; - } - - // @TODO check for existing location objects - // @TODO check firemaking level - - player.removeItem(removeFromSlot); - const worldItemLog = player.instance.spawnWorldItem(log, player.position, { owner: player, expires: 300 }); - - if(player.metadata['lastFire'] && Date.now() - player.metadata['lastFire'] < 1200 && - canChain(skillInfo.requiredLevel, player.skills.firemaking.level)) { - lightFire(player, position, worldItemLog, skillInfo.burnExp); - } else { - player.sendMessage(`You attempt to light the logs.`); - - let canLightFire = false; - let elapsedTicks = 0; - const loop = loopingEvent({ player }); - loop.event.subscribe(() => { - if(worldItemLog.removed) { - loop.cancel(); - return; - } - - if(canLightFire) { - loop.cancel(); - player.metadata.busy = true; - setTimeout(() => lightFire(player, position, worldItemLog, skillInfo.burnExp), 1200); - return; - } - - // @TODO check for existing location objects again (in-case one spawned here during this loop) - // @TODO check for tinderbox in-case it was removed - - if(elapsedTicks === 0 || elapsedTicks % 12 === 0) { - player.playAnimation(animationIds.lightingFire); - } - - canLightFire = elapsedTicks > 10 && canLight(skillInfo.requiredLevel, player.skills.firemaking.level); - - if(!canLightFire && (elapsedTicks === 0 || elapsedTicks % 4 === 0)) { - player.playSound(soundIds.lightingFire, 10, 0); - } else if(canLightFire) { - player.playSound(soundIds.fireLit, 7); - } - - elapsedTicks++; - }); - } -}; - -export default { - pluginId: 'rs:firemaking', - hooks: [ - { - type: 'item_on_item', - items: logs.map(log => ({ item1: itemIds.tinderbox, item2: log.logId })), - handler: action - } - ] -}; diff --git a/src/plugins/skills/firemaking/chance.ts b/src/plugins/skills/firemaking/chance.ts new file mode 100644 index 000000000..b8833d487 --- /dev/null +++ b/src/plugins/skills/firemaking/chance.ts @@ -0,0 +1,40 @@ +/** + * Roll a chance to light a fire. + * + * TODO (jameskmonger) this was ported from the old codebase and needs to be documented. + * + * @param logLevel The firemaking level required to light the log. + * @param playerLevel The player's current firemaking level. + * @returns `true` if the player successfully lights the fire, `false` otherwise. + */ +export const canLight = (logLevel: number, playerLevel: number): boolean => { + if (playerLevel < logLevel) { + return false; + } + + playerLevel++; + const hostRatio = Math.random() * logLevel; + const clientRatio = Math.random() * ((playerLevel - logLevel) * (1 + (logLevel * 0.01))); + return hostRatio < clientRatio; +}; + +/** + * Roll a chance to 'chain' a fire. + * + * TODO (jameskmonger) this was ported from the old codebase and needs to be documented. + * what is "chain"? + * + * @param logLevel The firemaking level required to light the log. + * @param playerLevel The player's current firemaking level. + * @returns `true` if the player successfully lights the fire, `false` otherwise. + */ +export const canChain = (logLevel: number, playerLevel: number): boolean => { + if (playerLevel < logLevel) { + return false; + } + + playerLevel++; + const hostRatio = Math.random() * logLevel; + const clientRatio = Math.random() * ((playerLevel - logLevel) * (1 + (logLevel * 0.01))); + return clientRatio - hostRatio < 3.5; +}; diff --git a/src/plugins/skills/firemaking/data.ts b/src/plugins/skills/firemaking/data.ts new file mode 100644 index 000000000..95dbebb17 --- /dev/null +++ b/src/plugins/skills/firemaking/data.ts @@ -0,0 +1,62 @@ +import { findItem } from '@engine/config'; +import { Burnable } from './types'; + +// using ! here because we know the items exist +export const FIREMAKING_LOGS: Burnable[] = [ + { + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logItem: findItem('rs:logs')!, + requiredLevel: 1, + experienceGained: 40 + }, + { + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logItem: findItem('rs:oak_logs')!, + requiredLevel: 15, + experienceGained: 60 + }, + { + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logItem: findItem('rs:willow_logs')!, + requiredLevel: 30, + experienceGained: 90 + }, + { + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logItem: findItem('rs:teak_logs')!, + requiredLevel: 35, + experienceGained: 105 + }, + { + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logItem: findItem('rs:maple_logs')!, + requiredLevel: 45, + experienceGained: 135 + }, + { + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logItem: findItem('rs:mahogany_logs')!, + requiredLevel: 50, + experienceGained: 157.5 + }, + { + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logItem: findItem('rs:yew_logs')!, + requiredLevel: 60, + experienceGained: 202.5 + }, + { + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + logItem: findItem('rs:magic_logs')!, + requiredLevel: 75, + experienceGained: 303.8 + } +]; diff --git a/src/plugins/skills/firemaking/firemaking-task.ts b/src/plugins/skills/firemaking/firemaking-task.ts new file mode 100644 index 000000000..878a07956 --- /dev/null +++ b/src/plugins/skills/firemaking/firemaking-task.ts @@ -0,0 +1,129 @@ +import { ActorWorldItemInteractionTask } from '@engine/task/impl'; +import { WorldItem } from '@engine/world'; +import { Player } from '@engine/world/actor'; +import { animationIds, soundIds } from '@engine/world/config'; +import { canLight } from './chance'; +import { FIREMAKING_LOGS } from './data'; +import { lightFire } from './light-fire'; +import { Burnable } from './types'; + +/** + * A firemaking task on a {@link WorldItem} log. + * + * This task extends {@link ActorWorldItemInteractionTask} which is a task that + * handles the interaction between an {@link Actor} and a {@link WorldItem}. + * + * The {@link ActorWalkToTask} (which our parent class extends) automatically + * sets a {@link TaskBreakType} of {@link TaskBreakType.ON_MOVE} which will + * cancel this task if the player clicks to move. + * + * By default, the {@link ActorWalkToTask} also sets a {@link TaskStackType} of + * {@link TaskStackType.NEVER} and a {@link TaskStackGroup} of {@link TaskStackGroup.ACTION} + * which means that this other actions will cancel the firemaking attempts. + * + * @author jameskmonger + */ +class FiremakingTask extends ActorWorldItemInteractionTask { + /** + * The log being lit. + */ + private logInfo: Burnable; + + /** + * The number of ticks that `execute` has been called inside this task. + */ + private elapsedTicks = 0; + private canLightFire = false; + + /** + * Create a new firemaking task. + * + * @param player The player that is attempting to light the fire. + * @param logWorldItem The world item that represents the log. + */ + constructor( + player: Player, + logWorldItem: WorldItem + ) { + super(player, logWorldItem); + + const logInfo = FIREMAKING_LOGS.find(l => l.logItem.gameId === logWorldItem.itemId); + + if (!logInfo) { + throw new Error(`Invalid firemaking log item id: ${logWorldItem.itemId}`); + } + + this.logInfo = logInfo; + } + + /** + * Execute the main firemaking task loop. This method is called every game tick until the task is completed. + * + * As this task extends {@link ActorWorldItemInteractionTask}, it's important that the + * {@link super.execute} method is called at the start of this method. + * + * The base `execute` performs a number of checks that allow this task to function healthily. + */ + public execute() { + super.execute(); + + /** + * As this task extends {@link ActorWorldItemInteractionTask}, the base classes {@link ActorWorldItemInteractionTask["worldItem"]} + * property will be null if the item isn't valid anymore or the player isn't in the right position. + * + * Therefore if `worldItem` is null, we can return early here, as our player is likely walking to the task. + */ + if (!this.worldItem) { + return; + } + + // store the tick count before incrementing so we don't need to keep track of it in all the separate branches + const tickCount = this.elapsedTicks++; + + if (this.canLightFire) { + if (tickCount === 2) { + lightFire(this.actor, this.actor.position, this.worldItem, this.logInfo.experienceGained); + this.stop(); + } + + // the rest of the function is for *attempting* to light the fire + // so we can return early here + return; + } + + // play animation every 12 ticks + if (tickCount % 12 === 0) { + this.actor.playAnimation(animationIds.lightingFire); + } + + // TODO (jameskmonger) reconsider this, is there a minimum tick count? + // OSRS wiki implies that there isn't + // https://oldschool.runescape.wiki/w/Firemaking#Success_chance + const passedMinimumThreshold = tickCount > 10; + this.canLightFire = passedMinimumThreshold && canLight(this.logInfo.requiredLevel, this.actor.skills.firemaking.level); + + // if we can now light the fire, reset the timer so that on the next tick we can begin lighting the fire + if (this.canLightFire) { + this.elapsedTicks = 0; + this.actor.busy = true; + this.actor.playSound(soundIds.fireLit, 7); + + return; + } + + // play lighting sound every 4th tick + if (tickCount % 4 === 0) { + this.actor.playSound(soundIds.lightingFire, 10, 0); + } + } +} + +/** + * Run the firemaking task for a player. + * + * @param player The player that is attempting to light the fire. + * @param worldItemLog The WorldItem that represents the log. + */ +export function runFiremakingTask(player: Player, worldItemLog: WorldItem) { + player.enqueueTask(FiremakingTask, [ worldItemLog ]); +} diff --git a/src/plugins/skills/firemaking/index.ts b/src/plugins/skills/firemaking/index.ts new file mode 100644 index 000000000..00389888d --- /dev/null +++ b/src/plugins/skills/firemaking/index.ts @@ -0,0 +1,73 @@ +import { itemOnItemActionHandler, ItemOnItemActionHook, ItemOnWorldItemActionHook } from '@engine/action'; +import { itemIds } from '@engine/world/config'; +import { FIREMAKING_LOGS } from './data'; +import { canChain } from './chance'; +import { canLightFireAtCurrentPosition, lightFire } from './light-fire'; +import { runFiremakingTask } from './firemaking-task'; + +/** + * Action hook for lighting a log with a tinderbox in the player's inventory. + */ +const tinderboxOnLogHandler: itemOnItemActionHandler = (details) => { + const { player, usedItem, usedWithItem, usedSlot, usedWithSlot } = details; + + if (player.metadata.lastFire && Date.now() - player.metadata.lastFire < 600) { + return; + } + + const log = usedItem.itemId !== itemIds.tinderbox ? usedItem : usedWithItem; + const removeFromSlot = usedItem.itemId !== itemIds.tinderbox ? usedSlot : usedWithSlot; + const skillInfo = FIREMAKING_LOGS.find(l => l.logItem.gameId === log.itemId); + + if (!skillInfo) { + player.sendMessage(`Mishandled firemaking log ${log.itemId}.`); + return; + } + + if (player.skills.firemaking.level < skillInfo.requiredLevel) { + player.sendMessage(`You need a Firemaking level of ${skillInfo.requiredLevel} to light this log.`); + return; + } + + if (!canLightFireAtCurrentPosition(player)) { + player.sendMessage('You cannot light a fire here.'); + return; + } + + player.removeItem(removeFromSlot); + const worldItemLog = player.instance.spawnWorldItem(log, player.position, { owner: player, expires: 300 }); + + // TODO (jameskmonger) chaining functionality needs documentation, I can't find anything about it online + if (player.metadata.lastFire && Date.now() - player.metadata.lastFire < 1200 && + canChain(skillInfo.requiredLevel, player.skills.firemaking.level)) { + lightFire(player, player.position, worldItemLog, skillInfo.experienceGained); + } else { + player.sendMessage('You attempt to light the logs.'); + + runFiremakingTask(player, worldItemLog); + } +}; + +/** + * Firemaking plugin + * + * TODO: + * - Document/remove `canChain` functionality - this is not documented anywhere online (RS wiki etc) + */ +export default { + pluginId: 'rs:firemaking', + hooks: [ + { + type: 'item_on_item', + items: FIREMAKING_LOGS.map(log => ({ item1: itemIds.tinderbox, item2: log.logItem.gameId })), + handler: tinderboxOnLogHandler + } as ItemOnItemActionHook, + { + type: 'item_on_world_item', + items: FIREMAKING_LOGS.map(log => ({ item: itemIds.tinderbox, worldItem: log.logItem.gameId })), + handler: ({ player, usedWithItem }) => { + runFiremakingTask(player, usedWithItem); + } + } as ItemOnWorldItemActionHook + ] +}; diff --git a/src/plugins/skills/firemaking/light-fire.ts b/src/plugins/skills/firemaking/light-fire.ts new file mode 100644 index 000000000..3aa9d534b --- /dev/null +++ b/src/plugins/skills/firemaking/light-fire.ts @@ -0,0 +1,77 @@ +import { randomBetween } from '@engine/util'; +import { Position, WorldItem } from '@engine/world'; +import { Player } from '@engine/world/actor'; +import { objectIds, itemIds } from '@engine/world/config'; +import { LandscapeObject } from '@runejs/filestore'; + +const fireDurationTicks = (): number => { + return randomBetween(100, 200); // 1-2 minutes +}; + +/** + * Whether or not a fire can be lit at the player's position. + * + * This is `true` if there are no spawned objects at the specified position of type 10. + * + * Probably should be moved to a more generic location (maybe on WorldInstance) + * + * @param player The player attempting to light the fire. + * @returns `true` if a fire can be lit at the specified position, `false` otherwise. + * + * @author jameskmonger + */ +export const canLightFireAtCurrentPosition = (player: Player): boolean => { + const existingFire = player.instance.getTileModifications(player.position).mods.spawnedObjects.find(o => ( + o.x === player.position.x + && o.y === player.position.y + && o.level === player.position.level + && o.type === 10 + )) + + return existingFire === undefined; +} + +/** + * Light a fire at the specified position. + * + * @param player The player lighting the fire. + * @param position The position to light the fire at. + * @param worldItemLog The world item representing the log. + * @param burnExp The experience gained for lighting the fire. + */ +export const lightFire = (player: Player, position: Position, worldItemLog: WorldItem, burnExp: number): void => { + if (!canLightFireAtCurrentPosition(player)) { + player.sendMessage('You cannot light a fire here.'); + return; + } + + player.instance.despawnWorldItem(worldItemLog); + const fireObject: LandscapeObject = { + objectId: objectIds.fire, + x: position.x, + y: position.y, + level: position.level, + type: 10, + orientation: 0 + }; + + player.playAnimation(null); + player.sendMessage('The fire catches and the logs begin to burn.'); + player.skills.firemaking.addExp(burnExp); + + if(!player.walkingQueue.moveIfAble(-1, 0)) { + if(!player.walkingQueue.moveIfAble(1, 0)) { + if(!player.walkingQueue.moveIfAble(0, -1)) { + player.walkingQueue.moveIfAble(0, 1); + } + } + } + + player.instance.spawnTemporaryGameObject(fireObject, position, fireDurationTicks()).then(() => { + player.instance.spawnWorldItem({ itemId: itemIds.ashes, amount: 1 }, position, { expires: 300 }); + }); + + player.face(position, false); + player.metadata.lastFire = Date.now(); + player.busy = false; +}; diff --git a/src/plugins/skills/firemaking/types.ts b/src/plugins/skills/firemaking/types.ts new file mode 100644 index 000000000..a11534ab9 --- /dev/null +++ b/src/plugins/skills/firemaking/types.ts @@ -0,0 +1,21 @@ +import { ItemDetails } from '@engine/config'; + +/** + * The definition for a burnable log. + */ +export type Burnable = { + /** + * The item details for the log. + */ + logItem: ItemDetails; + + /** + * The firemaking level required to light the log. + */ + requiredLevel: number; + + /** + * The experience gained for lighting the log. + */ + experienceGained: number; +} diff --git a/src/plugins/skills/fletching/fletching.plugin.ts b/src/plugins/skills/fletching/fletching.plugin.ts index eb21cc862..653b558a3 100644 --- a/src/plugins/skills/fletching/fletching.plugin.ts +++ b/src/plugins/skills/fletching/fletching.plugin.ts @@ -1,17 +1,17 @@ -import { itemOnItemActionHandler } from '@engine/world/action/item-on-item.action'; +import { itemOnItemActionHandler } from '@engine/action'; import { Player } from '@engine/world/actor/player/player'; import { randomBetween } from '@engine/util/num'; import { itemIds } from '@engine/world/config/item-ids'; import { animationIds } from '@engine/world/config/animation-ids'; -import { loopingEvent } from '@engine/game-server'; -import { buttonActionHandler, ButtonAction } from '@engine/world/action/button.action'; +import { buttonActionHandler, ButtonAction } from '@engine/action'; import { Skill } from '@engine/world/actor/skills'; import { widgetButtonIds, widgetItems } from '@plugins/skills/smithing/smelting-constants'; import { soundIds } from '@engine/world/config/sound-ids'; import { colors } from '@engine/util/colors'; -import { findItem, widgets } from '@engine/config'; +import { findItem, widgets } from '@engine/config/config-handler'; import { Fletchable } from '@plugins/skills/fletching/fletching-types'; -import { itemInteractionActionHandler } from '@engine/world/action/item-interaction.action'; +import { itemInteractionActionHandler } from '@engine/action'; +import { loopingEvent } from '@engine/plugins'; //fletching stuff goes below this! lets do it! diff --git a/src/plugins/skills/level-up-dialogue.plugin.ts b/src/plugins/skills/level-up-dialogue.plugin.ts index a71249f15..bd7b06008 100644 --- a/src/plugins/skills/level-up-dialogue.plugin.ts +++ b/src/plugins/skills/level-up-dialogue.plugin.ts @@ -1,4 +1,4 @@ -import { widgetInteractionActionHandler } from '@engine/world/action/widget-interaction.action'; +import { widgetInteractionActionHandler } from '@engine/action'; const widgetIds = [ 158, 161, 175, @@ -13,8 +13,8 @@ const widgetIds = [ /** * Handles a level-up dialogue action. */ -export const handler: widgetInteractionActionHandler = ({ player }) => - player.interfaceState.closeWidget('chatbox'); +export const handler: widgetInteractionActionHandler = ({ player }) => player.interfaceState.closeChatOverlayWidget(); + export default { pluginId: 'rs:close_level_up_message', diff --git a/src/plugins/skills/mining/mining.plugin.ts b/src/plugins/skills/mining/mining.plugin.ts index 56b6579ea..72bca2cd2 100644 --- a/src/plugins/skills/mining/mining.plugin.ts +++ b/src/plugins/skills/mining/mining.plugin.ts @@ -1,4 +1,4 @@ -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { Skill } from '@engine/world/actor/skills'; import { canInitiateHarvest, handleHarvesting } from '@engine/world/skill-util/harvest-skill'; import { getAllOreIds, getOreFromRock } from '@engine/world/config/harvestable-object'; diff --git a/src/plugins/skills/mining/prospecting.plugin.ts b/src/plugins/skills/mining/prospecting.plugin.ts index 3b7741ccb..0fd0212b6 100644 --- a/src/plugins/skills/mining/prospecting.plugin.ts +++ b/src/plugins/skills/mining/prospecting.plugin.ts @@ -1,9 +1,8 @@ -import { objectInteractionActionHandler } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler } from '@engine/action'; import { soundIds } from '@engine/world/config/sound-ids'; import { World } from '@engine/world'; -import { filestore } from '@engine/game-server'; import { getAllOreIds, getOreFromRock } from '@engine/world/config/harvestable-object'; -import { findItem } from '@engine/config'; +import { findItem } from '@engine/config/config-handler'; const action: objectInteractionActionHandler = (details) => { details.player.sendMessage('You examine the rock for ores.'); @@ -11,12 +10,19 @@ const action: objectInteractionActionHandler = (details) => { const ore = getOreFromRock(details.object.objectId); details.player.playSound(soundIds.oreEmpty, 7, 0); + const oreItem = findItem(ore.itemId); + + if (!oreItem) { + details.player.sendMessage('Sorry, something went wrong. Please report this to a developer.'); + return; + } + setTimeout(() => { if (!ore) { details.player.sendMessage('There is current no ore available in this rock.'); return; } - const oreName = findItem(ore.itemId).name.toLowerCase().replace(' ore', ''); + const oreName = oreItem.name.toLowerCase().replace(' ore', ''); details.player.sendMessage(`This rock contains ${oreName}.`); }, World.TICK_LENGTH * 3); diff --git a/src/plugins/skills/prayer_bury.plugin.js b/src/plugins/skills/prayer_bury.plugin.js index 5b847aca2..d569f2d84 100644 --- a/src/plugins/skills/prayer_bury.plugin.js +++ b/src/plugins/skills/prayer_bury.plugin.js @@ -1,9 +1,9 @@ -import { itemIds } from '../../game-engine/world/config/item-ids'; -import { soundIds } from '../../game-engine/world/config/sound-ids'; -import { animationIds } from '../../game-engine/world/config/animation-ids'; -import { Achievements, giveAchievement } from '../../game-engine/world/actor/player/achievements'; -import { Skill } from '../../game-engine/world/actor/skills'; -import { widgets } from '../../game-engine/config'; +import { itemIds } from '../../engine/world/config/item-ids'; +import { soundIds } from '../../engine/world/config/sound-ids'; +import { animationIds } from '../../engine/world/config/animation-ids'; +import { Achievements, giveAchievement } from '../../engine/world/actor/player/achievements'; +import { Skill } from '../../engine/world/actor/skills'; +import { widgets } from '@engine/config/config-handler'; const buryBonesHandler = async ({ player, itemSlot }) => { player.playAnimation(animationIds.buryBones); diff --git a/src/plugins/skills/runecrafting/runecrafting-altar.plugin.ts b/src/plugins/skills/runecrafting/runecrafting-altar.plugin.ts index 6b36de379..8e4e99a51 100644 --- a/src/plugins/skills/runecrafting/runecrafting-altar.plugin.ts +++ b/src/plugins/skills/runecrafting/runecrafting-altar.plugin.ts @@ -8,20 +8,30 @@ import { runes, talismans, } from '@plugins/skills/runecrafting/runecrafting-constants'; -import { itemOnObjectActionHandler, ItemOnObjectAction } from '@engine/world/action/item-on-object.action'; -import { filestore } from '@engine/game-server'; -import { objectInteractionActionHandler, ObjectInteractionAction } from '@engine/world/action/object-interaction.action'; +import { itemOnObjectActionHandler, ItemOnObjectAction } from '@engine/action'; +import { objectInteractionActionHandler, ObjectInteractionAction } from '@engine/action'; import { RunecraftingAltar, RunecraftingRune } from '@plugins/skills/runecrafting/runecrafting-types'; import { itemIds } from '@engine/world/config/item-ids'; import { Player } from '@engine/world/actor/player/player'; import { Item } from '@engine/world/items/item'; -import { findItem } from '@engine/config'; +import { findItem } from '@engine/config/config-handler'; +import { logger } from '@runejs/common'; const enterAltar: itemOnObjectActionHandler = (details: ItemOnObjectAction) => { const { player, object, item } = details; - const altar: RunecraftingAltar = getEntityByAttr(altars, 'entranceId', object.objectId); - const rune: RunecraftingRune = getEntityByAttr(runes, 'altar.entranceId', object.objectId); + const altar = getEntityByAttr(altars, 'entranceId', object.objectId); + const rune = getEntityByAttr(runes, 'altar.entranceId', object.objectId); + + if (!altar) { + logger.error(`No altar [entrance] found for runecrafting altar plugin: ${object.objectId}`); + return; + } + + if (!rune) { + logger.error(`No rune found for runecrafting altar plugin: ${object.objectId}`); + return; + } if (item.itemId === itemIds.talismans.elemental) { if (rune.talisman.id === itemIds.talismans.air @@ -48,6 +58,12 @@ const enterAltar: itemOnObjectActionHandler = (details: ItemOnObjectAction) => { function finishEnterAltar(player: Player, item: Item, altar: RunecraftingAltar): void { const talisman = findItem(item.itemId); + + if (!talisman) { + logger.error(`No talisman found for runecrafting altar plugin: ${item.itemId}`); + return; + } + player.sendMessage(`You hold the ${talisman.name} towards the mysterious ruins.`); player.sendMessage(`You feel a powerful force take hold of you..`); player.teleport(altar.entrance); @@ -57,6 +73,12 @@ function finishEnterAltar(player: Player, item: Item, altar: RunecraftingAltar): const exitAltar: objectInteractionActionHandler = (details: ObjectInteractionAction) => { const { player, object } = details; const altar = getEntityByAttr(altars, 'portalId', object.objectId); + + if (!altar) { + logger.error(`No altar [exit] found for runecrafting altar plugin: ${object.objectId}`); + return; + } + player.teleport(altar.exit); }; diff --git a/src/plugins/skills/runecrafting/runecrafting-constants.ts b/src/plugins/skills/runecrafting/runecrafting-constants.ts index cf5ea2932..1a55fece7 100644 --- a/src/plugins/skills/runecrafting/runecrafting-constants.ts +++ b/src/plugins/skills/runecrafting/runecrafting-constants.ts @@ -204,7 +204,7 @@ export const runes: Map = new Map = new Map = new Map = new Map = new Map = new Map = new Map = new Map = new Map = new Map = new Map = new Map([ @@ -306,7 +306,7 @@ export const combinationRunes: Map = new Ma tiara: [tiaras.get('air'), tiaras.get('water')], runes: [runes.get('air'), runes.get('water')], xp: [8.0, 8.5] - }], + } as RunecraftingCombinationRune], ['dust', { id: 4696, level: 10, @@ -315,7 +315,7 @@ export const combinationRunes: Map = new Ma talisman: [talismans.get('air'), talismans.get('earth')], runes: [runes.get('air'), runes.get('earth')], tiara: [tiaras.get('air'), tiaras.get('earth')], - }], + } as RunecraftingCombinationRune], ['mud', { id: 4698, level: 13, @@ -324,7 +324,7 @@ export const combinationRunes: Map = new Ma talisman: [talismans.get('water'), talismans.get('earth')], runes: [runes.get('water'), runes.get('earth')], tiara: [tiaras.get('water'), tiaras.get('earth')], - }], + } as RunecraftingCombinationRune], ['smoke', { id: 4697, level: 15, @@ -333,7 +333,7 @@ export const combinationRunes: Map = new Ma talisman: [talismans.get('air'), talismans.get('fire')], runes: [runes.get('air'), runes.get('fire')], tiara: [tiaras.get('air'), tiaras.get('fire')], - }], + } as RunecraftingCombinationRune], ['steam', { id: 4694, level: 19, @@ -342,7 +342,7 @@ export const combinationRunes: Map = new Ma talisman: [talismans.get('water'), talismans.get('fire')], runes: [runes.get('water'), runes.get('fire')], tiara: [tiaras.get('water'), tiaras.get('fire')], - }], + } as RunecraftingCombinationRune], ['lava', { id: 4699, level: 23, @@ -351,11 +351,11 @@ export const combinationRunes: Map = new Ma talisman: [talismans.get('earth'), talismans.get('fire')], runes: [runes.get('earth'), runes.get('fire')], tiara: [tiaras.get('earth'), tiaras.get('fire')], - }] + } as RunecraftingCombinationRune], ]); -export function getEntityByAttr(entities: Map, attr: string, value: unknown): T { - let entity = undefined; +export function getEntityByAttr(entities: Map, attr: string, value: unknown): T | null { + let entity: T | null = null; const splits = attr.split('.'); // Handles dot seperated attribute names. @@ -399,4 +399,6 @@ export function runeMultiplier(runeId: number, level: number): number { case 563: return 1.0; case 560: return 1.0; } + + return 1.0; } diff --git a/src/plugins/skills/runecrafting/runecrafting-crafting.plugin.ts b/src/plugins/skills/runecrafting/runecrafting-crafting.plugin.ts index e6e647b16..4518fdc50 100644 --- a/src/plugins/skills/runecrafting/runecrafting-crafting.plugin.ts +++ b/src/plugins/skills/runecrafting/runecrafting-crafting.plugin.ts @@ -2,7 +2,7 @@ * @Author NickNick */ -import { objectInteractionActionHandler, ObjectInteractionAction } from '@engine/world/action/object-interaction.action'; +import { objectInteractionActionHandler, ObjectInteractionAction } from '@engine/action'; import { Skill } from '@engine/world/actor/skills'; import { altars, combinationRunes, @@ -10,18 +10,30 @@ import { getEntityIds, runeMultiplier, runes, } from '@plugins/skills/runecrafting/runecrafting-constants'; -import { itemOnObjectActionHandler, ItemOnObjectAction } from '@engine/world/action/item-on-object.action'; +import { itemOnObjectActionHandler, ItemOnObjectAction } from '@engine/action'; import { RunecraftingCombinationRune } from '@plugins/skills/runecrafting/runecrafting-types'; import { randomBetween } from '@engine/util/num'; import { itemIds } from '@engine/world/config/item-ids'; -import { findItem, widgets } from '@engine/config'; +import { findItem, widgets } from '@engine/config/config-handler'; +import { logger } from '@runejs/common'; const craftRune: objectInteractionActionHandler = (details: ObjectInteractionAction) => { const { player, object } = details; const rune = getEntityByAttr(runes, 'altar.craftingId', object.objectId); + + if (!rune) { + logger.error(`No rune [crafting] found for runecrafting plugin: ${object.objectId}`); + return; + } + const runeDetails = findItem(rune.id); + if (!runeDetails) { + logger.warn(`Could not find rune details for rune id ${rune.id}`); + return; + } + const level = player.skills.get(Skill.RUNECRAFTING).level; if (level < rune.level) { player.sendMessage(`You need a runecrafting level of ${rune.level} to craft ${runeDetails.name}.`); @@ -52,15 +64,13 @@ const craftRune: objectInteractionActionHandler = (details: ObjectInteractionAct }; function getCombinationRuneByAltar(itemId: number, objectId: number): RunecraftingCombinationRune | undefined { - let rune = undefined; for (const combinationRune of combinationRunes.values()) { const altarIndex = combinationRune.altar.findIndex((altar) => altar.craftingId === objectId); if (altarIndex > -1 && combinationRune.talisman[altarIndex ^ 1].id === itemId) { - rune = combinationRune; - break; + return combinationRune; } } - return rune; + return undefined; } const craftCombinationRune: itemOnObjectActionHandler = (details: ItemOnObjectAction) => { @@ -80,6 +90,11 @@ const craftCombinationRune: itemOnObjectActionHandler = (details: ItemOnObjectAc } const runeDetails = findItem(rune.id); + if (!runeDetails) { + logger.warn(`Could not find rune details for rune id ${rune.id}`); + return; + } + const level = player.skills.get(Skill.RUNECRAFTING).level; if (level < rune.level) { player.sendMessage(`You need a runecrafting level of ${rune.level} to craft ${runeDetails.name}.`); diff --git a/src/plugins/skills/runecrafting/runecrafting-tiara.plugin.ts b/src/plugins/skills/runecrafting/runecrafting-tiara.plugin.ts index 521853e62..dc4dff944 100644 --- a/src/plugins/skills/runecrafting/runecrafting-tiara.plugin.ts +++ b/src/plugins/skills/runecrafting/runecrafting-tiara.plugin.ts @@ -3,7 +3,8 @@ */ import { getEntityByAttr, getEntityIds, tiaras } from '@plugins/skills/runecrafting/runecrafting-constants'; -import { equipmentChangeActionHandler } from '@engine/world/action/equipment-change.action'; +import { equipmentChangeActionHandler } from '@engine/action'; +import { logger } from '@runejs/common'; const unequipTiara : equipmentChangeActionHandler = (details) => { @@ -14,6 +15,12 @@ const unequipTiara : equipmentChangeActionHandler = (details) => { const equipTiara : equipmentChangeActionHandler = (details) => { const { player, itemId } = details; const tiara = getEntityByAttr(tiaras, 'id', itemId); + + if (!tiara) { + logger.error(`No tiara [equipping] found for runecrafting plugin: ${itemId}`); + return; + } + player.outgoingPackets.updateClientConfig(491, tiara.config); }; diff --git a/data/config/skill-guides/Strength.json b/src/plugins/skills/skill-guides/Strength.json similarity index 100% rename from data/config/skill-guides/Strength.json rename to src/plugins/skills/skill-guides/Strength.json diff --git a/data/config/skill-guides/agility.json b/src/plugins/skills/skill-guides/agility.json similarity index 100% rename from data/config/skill-guides/agility.json rename to src/plugins/skills/skill-guides/agility.json diff --git a/data/config/skill-guides/attack.json b/src/plugins/skills/skill-guides/attack.json similarity index 100% rename from data/config/skill-guides/attack.json rename to src/plugins/skills/skill-guides/attack.json diff --git a/data/config/skill-guides/construction.json b/src/plugins/skills/skill-guides/construction.json similarity index 100% rename from data/config/skill-guides/construction.json rename to src/plugins/skills/skill-guides/construction.json diff --git a/data/config/skill-guides/cooking.json b/src/plugins/skills/skill-guides/cooking.json similarity index 100% rename from data/config/skill-guides/cooking.json rename to src/plugins/skills/skill-guides/cooking.json diff --git a/data/config/skill-guides/crafting.json b/src/plugins/skills/skill-guides/crafting.json similarity index 100% rename from data/config/skill-guides/crafting.json rename to src/plugins/skills/skill-guides/crafting.json diff --git a/data/config/skill-guides/Defence.json b/src/plugins/skills/skill-guides/defence.json similarity index 100% rename from data/config/skill-guides/Defence.json rename to src/plugins/skills/skill-guides/defence.json diff --git a/data/config/skill-guides/farming.json b/src/plugins/skills/skill-guides/farming.json similarity index 100% rename from data/config/skill-guides/farming.json rename to src/plugins/skills/skill-guides/farming.json diff --git a/data/config/skill-guides/firemaking.json b/src/plugins/skills/skill-guides/firemaking.json similarity index 100% rename from data/config/skill-guides/firemaking.json rename to src/plugins/skills/skill-guides/firemaking.json diff --git a/data/config/skill-guides/fishing.json b/src/plugins/skills/skill-guides/fishing.json similarity index 100% rename from data/config/skill-guides/fishing.json rename to src/plugins/skills/skill-guides/fishing.json diff --git a/data/config/skill-guides/fletching.json b/src/plugins/skills/skill-guides/fletching.json similarity index 100% rename from data/config/skill-guides/fletching.json rename to src/plugins/skills/skill-guides/fletching.json diff --git a/data/config/skill-guides/herblore.json b/src/plugins/skills/skill-guides/herblore.json similarity index 100% rename from data/config/skill-guides/herblore.json rename to src/plugins/skills/skill-guides/herblore.json diff --git a/data/config/skill-guides/hitpoint.json b/src/plugins/skills/skill-guides/hitpoint.json similarity index 100% rename from data/config/skill-guides/hitpoint.json rename to src/plugins/skills/skill-guides/hitpoint.json diff --git a/data/config/skill-guides/magic.json b/src/plugins/skills/skill-guides/magic.json similarity index 100% rename from data/config/skill-guides/magic.json rename to src/plugins/skills/skill-guides/magic.json diff --git a/data/config/skill-guides/mining.json b/src/plugins/skills/skill-guides/mining.json similarity index 100% rename from data/config/skill-guides/mining.json rename to src/plugins/skills/skill-guides/mining.json diff --git a/data/config/skill-guides/prayer.json b/src/plugins/skills/skill-guides/prayer.json similarity index 100% rename from data/config/skill-guides/prayer.json rename to src/plugins/skills/skill-guides/prayer.json diff --git a/data/config/skill-guides/Ranged.json b/src/plugins/skills/skill-guides/ranged.json similarity index 100% rename from data/config/skill-guides/Ranged.json rename to src/plugins/skills/skill-guides/ranged.json diff --git a/data/config/skill-guides/runecrafting.json b/src/plugins/skills/skill-guides/runecrafting.json similarity index 100% rename from data/config/skill-guides/runecrafting.json rename to src/plugins/skills/skill-guides/runecrafting.json diff --git a/src/game-engine/config/skill-guide-config.ts b/src/plugins/skills/skill-guides/skill-guide-config.ts similarity index 79% rename from src/game-engine/config/skill-guide-config.ts rename to src/plugins/skills/skill-guides/skill-guide-config.ts index 8a13c7a5a..2987ef90a 100644 --- a/src/game-engine/config/skill-guide-config.ts +++ b/src/plugins/skills/skill-guides/skill-guide-config.ts @@ -1,6 +1,6 @@ -import { loadConfigurationFiles } from '@runejs/core/fs'; -import { itemMap } from '@engine/config/index'; -import { ItemDetails } from '@engine/config/item-config'; +import { loadConfigurationFiles } from '@runejs/common/fs'; +import { itemMap, ItemDetails } from '@engine/config'; + /** * Skill Guide Configuration @@ -30,13 +30,17 @@ export interface SkillSubGuide { * @return SkillGuideConfiguration[] */ export async function loadSkillGuideConfigurations(path: string): Promise { - const skillGuides = []; + const skillGuides: SkillGuide[] = []; const files = await loadConfigurationFiles(path); files.forEach((skillGuide) => { - const subGuides = []; + if(!skillGuide?.sub_guides) { + return; + } + + const subGuides: SkillSubGuide[] = []; skillGuide.sub_guides.forEach((subGuide) => { - const subGuideLines = []; + const subGuideLines: SkillSubGuide['lines'] = []; subGuide.lines.forEach((line) => { subGuideLines.push({ item: itemMap[line.item], diff --git a/src/plugins/skills/skill-guide.plugin.ts b/src/plugins/skills/skill-guides/skill-guides.plugin.ts similarity index 74% rename from src/plugins/skills/skill-guide.plugin.ts rename to src/plugins/skills/skill-guides/skill-guides.plugin.ts index 5c6b320ff..ffc51d11f 100644 --- a/src/plugins/skills/skill-guide.plugin.ts +++ b/src/plugins/skills/skill-guides/skill-guides.plugin.ts @@ -1,21 +1,27 @@ -import { buttonActionHandler, ButtonActionHook } from '@engine/world/action/button.action'; -import { Player } from '@engine/world/actor/player/player'; import { + buttonActionHandler, + ButtonActionHook, widgetInteractionActionHandler, WidgetInteractionActionHook -} from '@engine/world/action/widget-interaction.action'; -import { skillGuides, widgets } from '@engine/config'; -import { SkillGuide, SkillSubGuide } from '@engine/config/skill-guide-config'; +} from '@engine/action'; +import { Player } from '@engine/world/actor'; +import { widgets } from '@engine/config'; +import { SkillGuide, SkillSubGuide, loadSkillGuideConfigurations } from './skill-guide-config'; +import { logger } from '@runejs/common'; -const guides = skillGuides; - +const skillGuidePath = __dirname.replace(/dist/, 'src'); const sidebarTextIds = [131, 108, 109, 112, 122, 125, 128, 143, 146, 149, 159, 162, 165]; const sidebarIds = [129, 98, -1, 110, 113, 123, 126, 134, 144, 147, 150, 160, 163]; -const buttonIds = guides.map(g => g.id); +let guides: SkillGuide[] = []; function loadGuide(player: Player, guideId: number, subGuideId: number = 0, refreshSidebar: boolean = true): void { - const guide: SkillGuide = guides.find(g => g.id === guideId); + const guide = guides.find(g => g.id === guideId); + + if (!guide) { + logger.error(`Could not find skill guide with id ${guideId}`); + return; + } if(refreshSidebar) { player.modifyWidget(widgets.skillGuide, { childId: 133, text: (guide.members ? 'Members only skill' : '') }); @@ -62,24 +68,39 @@ function loadGuide(player: Player, guideId: number, subGuideId: number = 0, refr slot: 'screen', multi: false }); - player.metadata['activeSkillGuide'] = guideId; + player.metadata.activeSkillGuide = guideId; } -export const guideHandler: buttonActionHandler = (details) => { +export const guideHandler: buttonActionHandler = async (details) => { const { player, buttonId } = details; + + if(!guides.length) { + guides = await loadSkillGuideConfigurations(skillGuidePath); + } + loadGuide(player, buttonId); }; -export const subGuideHandler: widgetInteractionActionHandler = (details) => { +export const subGuideHandler: widgetInteractionActionHandler = async (details) => { const { player, childId } = details; - const activeSkillGuide = player.metadata['activeSkillGuide']; + if(!guides.length) { + guides = await loadSkillGuideConfigurations(skillGuidePath); + } + + const activeSkillGuide = player.metadata.activeSkillGuide; if(!activeSkillGuide) { return; } const guide = guides.find(g => g.id === activeSkillGuide); + + if (!guide) { + logger.error(`Could not find skill guide with id ${activeSkillGuide}`); + return; + } + const subGuideId = sidebarTextIds.indexOf(childId); if(subGuideId >= guide.sub_guides.length) { @@ -95,13 +116,11 @@ export default { { type: 'button', widgetId: widgets.skillsTab, - buttonIds, handler: guideHandler } as ButtonActionHook, { type: 'widget_interaction', widgetIds: widgets.skillGuide, - childIds: sidebarTextIds, optionId: 0, handler: subGuideHandler } as WidgetInteractionActionHook diff --git a/data/config/skill-guides/slayer.json b/src/plugins/skills/skill-guides/slayer.json similarity index 100% rename from data/config/skill-guides/slayer.json rename to src/plugins/skills/skill-guides/slayer.json diff --git a/data/config/skill-guides/smithing.json b/src/plugins/skills/skill-guides/smithing.json similarity index 100% rename from data/config/skill-guides/smithing.json rename to src/plugins/skills/skill-guides/smithing.json diff --git a/data/config/skill-guides/thieving.json b/src/plugins/skills/skill-guides/thieving.json similarity index 100% rename from data/config/skill-guides/thieving.json rename to src/plugins/skills/skill-guides/thieving.json diff --git a/data/config/skill-guides/woodcutting.json b/src/plugins/skills/skill-guides/woodcutting.json similarity index 100% rename from data/config/skill-guides/woodcutting.json rename to src/plugins/skills/skill-guides/woodcutting.json diff --git a/src/plugins/skills/smithing/forging-constants.ts b/src/plugins/skills/smithing/forging-constants.ts index 8fd906575..aee677ee2 100644 --- a/src/plugins/skills/smithing/forging-constants.ts +++ b/src/plugins/skills/smithing/forging-constants.ts @@ -1644,257 +1644,260 @@ export const smithables : Map> = new Map> = new Map>([ [itemIds.bars.bronze, new Map([ [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger').get('bronze'), - smithables.get('sword').get('bronze'), - smithables.get('scimitar').get('bronze'), - smithables.get('longsword').get('bronze'), - smithables.get('twoHandedSword').get('bronze'), + smithables.get('dagger')?.get('bronze') as Smithable, + smithables.get('sword')?.get('bronze') as Smithable, + smithables.get('scimitar')?.get('bronze') as Smithable, + smithables.get('longsword')?.get('bronze') as Smithable, + smithables.get('twoHandedSword')?.get('bronze') as Smithable, ]], [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe').get('bronze'), - smithables.get('mace').get('bronze'), - smithables.get('warhammer').get('bronze'), - smithables.get('battleaxe').get('bronze'), - smithables.get('claws').get('bronze') + smithables.get('axe')?.get('bronze') as Smithable, + smithables.get('mace')?.get('bronze') as Smithable, + smithables.get('warhammer')?.get('bronze') as Smithable, + smithables.get('battleaxe')?.get('bronze') as Smithable, + smithables.get('claws')?.get('bronze') as Smithable ]], [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody').get('bronze'), - smithables.get('platelegs').get('bronze'), - smithables.get('plateskirt').get('bronze'), - smithables.get('platebody').get('bronze'), - smithables.get('unknown').get('any') + smithables.get('chainbody')?.get('bronze') as Smithable, + smithables.get('platelegs')?.get('bronze') as Smithable, + smithables.get('plateskirt')?.get('bronze') as Smithable, + smithables.get('platebody')?.get('bronze') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm').get('bronze'), - smithables.get('fullHelm').get('bronze'), - smithables.get('squareShield').get('bronze'), - smithables.get('kiteshield').get('bronze'), - smithables.get('nails').get('bronze') + smithables.get('mediumHelm')?.get('bronze') as Smithable, + smithables.get('fullHelm')?.get('bronze') as Smithable, + smithables.get('squareShield')?.get('bronze') as Smithable, + smithables.get('kiteshield')?.get('bronze') as Smithable, + smithables.get('nails')?.get('bronze') as Smithable ]], [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips').get('bronze'), - smithables.get('arrowTips').get('bronze'), - smithables.get('unknown').get('any'), - smithables.get('unknown').get('any'), - smithables.get('unknown').get('any') + smithables.get('dartTips')?.get('bronze') as Smithable, + smithables.get('arrowTips')?.get('bronze') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts').get('bronze'), - smithables.get('limbs').get('bronze'), - smithables.get('unknown').get('any'), + smithables.get('bolts')?.get('bronze') as Smithable, + smithables.get('limbs')?.get('bronze') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, ]] ])], [itemIds.bars.iron, new Map([ [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger').get('iron'), - smithables.get('sword').get('iron'), - smithables.get('scimitar').get('iron'), - smithables.get('longsword').get('iron'), - smithables.get('twoHandedSword').get('iron'), + smithables.get('dagger')?.get('iron') as Smithable, + smithables.get('sword')?.get('iron') as Smithable, + smithables.get('scimitar')?.get('iron') as Smithable, + smithables.get('longsword')?.get('iron') as Smithable, + smithables.get('twoHandedSword')?.get('iron') as Smithable, ]], [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe').get('iron'), - smithables.get('mace').get('iron'), - smithables.get('warhammer').get('iron'), - smithables.get('battleaxe').get('iron'), - smithables.get('claws').get('iron') + smithables.get('axe')?.get('iron') as Smithable, + smithables.get('mace')?.get('iron') as Smithable, + smithables.get('warhammer')?.get('iron') as Smithable, + smithables.get('battleaxe')?.get('iron') as Smithable, + smithables.get('claws')?.get('iron') as Smithable ]], [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody').get('iron'), - smithables.get('platelegs').get('iron'), - smithables.get('plateskirt').get('iron'), - smithables.get('platebody').get('iron'), - smithables.get('unknown').get('any') + smithables.get('chainbody')?.get('iron') as Smithable, + smithables.get('platelegs')?.get('iron') as Smithable, + smithables.get('plateskirt')?.get('iron') as Smithable, + smithables.get('platebody')?.get('iron') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm').get('iron'), - smithables.get('fullHelm').get('iron'), - smithables.get('squareShield').get('iron'), - smithables.get('kiteshield').get('iron'), - smithables.get('nails').get('iron') + smithables.get('mediumHelm')?.get('iron') as Smithable, + smithables.get('fullHelm')?.get('iron') as Smithable, + smithables.get('squareShield')?.get('iron') as Smithable, + smithables.get('kiteshield')?.get('iron') as Smithable, + smithables.get('nails')?.get('iron') as Smithable ]], [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips').get('iron'), - smithables.get('arrowTips').get('iron'), - smithables.get('unknown').get('any'), - smithables.get('unknown').get('any'), - smithables.get('unknown').get('any') + smithables.get('dartTips')?.get('iron') as Smithable, + smithables.get('arrowTips')?.get('iron') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts').get('iron'), - smithables.get('limbs').get('iron'), - smithables.get('unknown').get('any'), + smithables.get('bolts')?.get('iron') as Smithable, + smithables.get('limbs')?.get('iron') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, ]] ])], [itemIds.bars.steel, new Map([ [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger').get('steel'), - smithables.get('sword').get('steel'), - smithables.get('scimitar').get('steel'), - smithables.get('longsword').get('steel'), - smithables.get('twoHandedSword').get('steel'), + smithables.get('dagger')?.get('steel') as Smithable, + smithables.get('sword')?.get('steel') as Smithable, + smithables.get('scimitar')?.get('steel') as Smithable, + smithables.get('longsword')?.get('steel') as Smithable, + smithables.get('twoHandedSword')?.get('steel') as Smithable, ]], [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe').get('steel'), - smithables.get('mace').get('steel'), - smithables.get('warhammer').get('steel'), - smithables.get('battleaxe').get('steel'), - smithables.get('claws').get('steel') + smithables.get('axe')?.get('steel') as Smithable, + smithables.get('mace')?.get('steel') as Smithable, + smithables.get('warhammer')?.get('steel') as Smithable, + smithables.get('battleaxe')?.get('steel') as Smithable, + smithables.get('claws')?.get('steel') as Smithable ]], [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody').get('steel'), - smithables.get('platelegs').get('steel'), - smithables.get('plateskirt').get('steel'), - smithables.get('platebody').get('steel'), - smithables.get('unknown').get('any') + smithables.get('chainbody')?.get('steel') as Smithable, + smithables.get('platelegs')?.get('steel') as Smithable, + smithables.get('plateskirt')?.get('steel') as Smithable, + smithables.get('platebody')?.get('steel') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm').get('steel'), - smithables.get('fullHelm').get('steel'), - smithables.get('squareShield').get('steel'), - smithables.get('kiteshield').get('steel'), - smithables.get('nails').get('steel') + smithables.get('mediumHelm')?.get('steel') as Smithable, + smithables.get('fullHelm')?.get('steel') as Smithable, + smithables.get('squareShield')?.get('steel') as Smithable, + smithables.get('kiteshield')?.get('steel') as Smithable, + smithables.get('nails')?.get('steel') as Smithable ]], [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips').get('steel'), - smithables.get('arrowTips').get('steel'), - smithables.get('knife').get('steel'), - smithables.get('unknown').get('any'), - smithables.get('unknown').get('any') + smithables.get('dartTips')?.get('steel') as Smithable, + smithables.get('arrowTips')?.get('steel') as Smithable, + smithables.get('knife')?.get('steel') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts').get('steel'), - smithables.get('limbs').get('steel'), - smithables.get('unknown').get('any'), + smithables.get('bolts')?.get('steel') as Smithable, + smithables.get('limbs')?.get('steel') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, ]] ])], [itemIds.bars.mithril, new Map([ [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger').get('mithril'), - smithables.get('sword').get('mithril'), - smithables.get('scimitar').get('mithril'), - smithables.get('longsword').get('mithril'), - smithables.get('twoHandedSword').get('mithril'), + smithables.get('dagger')?.get('mithril') as Smithable, + smithables.get('sword')?.get('mithril') as Smithable, + smithables.get('scimitar')?.get('mithril') as Smithable, + smithables.get('longsword')?.get('mithril') as Smithable, + smithables.get('twoHandedSword')?.get('mithril') as Smithable, ]], [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe').get('mithril'), - smithables.get('mace').get('mithril'), - smithables.get('warhammer').get('mithril'), - smithables.get('battleaxe').get('mithril'), - smithables.get('claws').get('mithril') + smithables.get('axe')?.get('mithril') as Smithable, + smithables.get('mace')?.get('mithril') as Smithable, + smithables.get('warhammer')?.get('mithril') as Smithable, + smithables.get('battleaxe')?.get('mithril') as Smithable, + smithables.get('claws')?.get('mithril') as Smithable ]], [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody').get('mithril'), - smithables.get('platelegs').get('mithril'), - smithables.get('plateskirt').get('mithril'), - smithables.get('platebody').get('mithril'), - smithables.get('unknown').get('any') + smithables.get('chainbody')?.get('mithril') as Smithable, + smithables.get('platelegs')?.get('mithril') as Smithable, + smithables.get('plateskirt')?.get('mithril') as Smithable, + smithables.get('platebody')?.get('mithril') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm').get('mithril'), - smithables.get('fullHelm').get('mithril'), - smithables.get('squareShield').get('mithril'), - smithables.get('kiteshield').get('mithril'), - smithables.get('nails').get('mithril') + smithables.get('mediumHelm')?.get('mithril') as Smithable, + smithables.get('fullHelm')?.get('mithril') as Smithable, + smithables.get('squareShield')?.get('mithril') as Smithable, + smithables.get('kiteshield')?.get('mithril') as Smithable, + smithables.get('nails')?.get('mithril') as Smithable ]], [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips').get('mithril'), - smithables.get('arrowTips').get('mithril'), - smithables.get('knife').get('mithril'), - smithables.get('unknown').get('any'), - smithables.get('unknown').get('any') + smithables.get('dartTips')?.get('mithril') as Smithable, + smithables.get('arrowTips')?.get('mithril') as Smithable, + smithables.get('knife')?.get('mithril') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts').get('mithril'), - smithables.get('limbs').get('mithril'), - smithables.get('unknown').get('any'), + smithables.get('bolts')?.get('mithril') as Smithable, + smithables.get('limbs')?.get('mithril') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, ]] ])], [itemIds.bars.adamantite, new Map([ [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger').get('adamant'), - smithables.get('sword').get('adamant'), - smithables.get('scimitar').get('adamant'), - smithables.get('longsword').get('adamant'), - smithables.get('twoHandedSword').get('adamant'), + smithables.get('dagger')?.get('adamant') as Smithable, + smithables.get('sword')?.get('adamant') as Smithable, + smithables.get('scimitar')?.get('adamant') as Smithable, + smithables.get('longsword')?.get('adamant') as Smithable, + smithables.get('twoHandedSword')?.get('adamant') as Smithable, ]], [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe').get('adamant'), - smithables.get('mace').get('adamant'), - smithables.get('warhammer').get('adamant'), - smithables.get('battleaxe').get('adamant'), - smithables.get('claws').get('adamant') + smithables.get('axe')?.get('adamant') as Smithable, + smithables.get('mace')?.get('adamant') as Smithable, + smithables.get('warhammer')?.get('adamant') as Smithable, + smithables.get('battleaxe')?.get('adamant') as Smithable, + smithables.get('claws')?.get('adamant') as Smithable ]], [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody').get('adamant'), - smithables.get('platelegs').get('adamant'), - smithables.get('plateskirt').get('adamant'), - smithables.get('platebody').get('adamant'), - smithables.get('unknown').get('any') + smithables.get('chainbody')?.get('adamant') as Smithable, + smithables.get('platelegs')?.get('adamant') as Smithable, + smithables.get('plateskirt')?.get('adamant') as Smithable, + smithables.get('platebody')?.get('adamant') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm').get('adamant'), - smithables.get('fullHelm').get('adamant'), - smithables.get('squareShield').get('adamant'), - smithables.get('kiteshield').get('adamant'), - smithables.get('nails').get('adamant') + smithables.get('mediumHelm')?.get('adamant') as Smithable, + smithables.get('fullHelm')?.get('adamant') as Smithable, + smithables.get('squareShield')?.get('adamant') as Smithable, + smithables.get('kiteshield')?.get('adamant') as Smithable, + smithables.get('nails')?.get('adamant') as Smithable ]], [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips').get('adamant'), - smithables.get('arrowTips').get('adamant'), - smithables.get('knife').get('adamant'), - smithables.get('unknown').get('any'), - smithables.get('unknown').get('any') + smithables.get('dartTips')?.get('adamant') as Smithable, + smithables.get('arrowTips')?.get('adamant') as Smithable, + smithables.get('knife')?.get('adamant') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts').get('adamant'), - smithables.get('limbs').get('adamant'), - smithables.get('unknown').get('any'), + smithables.get('bolts')?.get('adamant') as Smithable, + smithables.get('limbs')?.get('adamant') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, ]] ])], [itemIds.bars.runite, new Map([ [146, [ // Dagger, Sword, Scimitar, Longsword, 2h sword - smithables.get('dagger').get('rune'), - smithables.get('sword').get('rune'), - smithables.get('scimitar').get('rune'), - smithables.get('longsword').get('rune'), - smithables.get('twoHandedSword').get('rune'), + smithables.get('dagger')?.get('rune') as Smithable, + smithables.get('sword')?.get('rune') as Smithable, + smithables.get('scimitar')?.get('rune') as Smithable, + smithables.get('longsword')?.get('rune') as Smithable, + smithables.get('twoHandedSword')?.get('rune') as Smithable, ]], [147, [ // Axe, Mace, Warhammer, Battleaxe, Claws - smithables.get('axe').get('rune'), - smithables.get('mace').get('rune'), - smithables.get('warhammer').get('rune'), - smithables.get('battleaxe').get('rune'), - smithables.get('claws').get('rune') + smithables.get('axe')?.get('rune') as Smithable, + smithables.get('mace')?.get('rune') as Smithable, + smithables.get('warhammer')?.get('rune') as Smithable, + smithables.get('battleaxe')?.get('rune') as Smithable, + smithables.get('claws')?.get('rune') as Smithable ]], [148, [ // Chainbody, Platelegs, Plateskirt, Platebody, *Lantern* - smithables.get('chainbody').get('rune'), - smithables.get('platelegs').get('rune'), - smithables.get('plateskirt').get('rune'), - smithables.get('platebody').get('rune'), - smithables.get('unknown').get('any') + smithables.get('chainbody')?.get('rune') as Smithable, + smithables.get('platelegs')?.get('rune') as Smithable, + smithables.get('plateskirt')?.get('rune') as Smithable, + smithables.get('platebody')?.get('rune') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [149, [ // Medium helm, Full helm, Sq shield, kite shield, Nails - smithables.get('mediumHelm').get('rune'), - smithables.get('fullHelm').get('rune'), - smithables.get('squareShield').get('rune'), - smithables.get('kiteshield').get('rune'), - smithables.get('nails').get('rune') + smithables.get('mediumHelm')?.get('rune') as Smithable, + smithables.get('fullHelm')?.get('rune') as Smithable, + smithables.get('squareShield')?.get('rune') as Smithable, + smithables.get('kiteshield')?.get('rune') as Smithable, + smithables.get('nails')?.get('rune') as Smithable ]], [150, [ // Dart tip, Arrowtips, Throwing knives, *Other*, *Studs* - smithables.get('dartTips').get('rune'), - smithables.get('arrowTips').get('rune'), - smithables.get('knife').get('rune'), - smithables.get('unknown').get('any'), - smithables.get('unknown').get('any') + smithables.get('dartTips')?.get('rune') as Smithable, + smithables.get('arrowTips')?.get('rune') as Smithable, + smithables.get('knife')?.get('rune') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, + smithables.get('unknown')?.get('any') as Smithable ]], [151, [ // Bolts, Limbs, Grapple tips - smithables.get('bolts').get('rune'), - smithables.get('limbs').get('rune'), - smithables.get('unknown').get('any'), + smithables.get('bolts')?.get('rune') as Smithable, + smithables.get('limbs')?.get('rune') as Smithable, + smithables.get('unknown')?.get('any') as Smithable, ]] ])] ]); diff --git a/src/plugins/skills/smithing/forging.plugin.ts b/src/plugins/skills/smithing/forging.plugin.ts index 07affaba4..06434bf7a 100644 --- a/src/plugins/skills/smithing/forging.plugin.ts +++ b/src/plugins/skills/smithing/forging.plugin.ts @@ -1,17 +1,15 @@ -import { itemOnObjectActionHandler, ItemOnObjectActionHook } from '@engine/world/action/item-on-object.action'; -import { widgets } from '@engine/config'; +import { + itemOnObjectActionHandler, ItemOnObjectActionHook, ItemInteractionAction, ItemInteractionActionHook, TaskExecutor +} from '@engine/action'; +import { widgets } from '@engine/config/config-handler'; import { Skill } from '@engine/world/actor/skills'; import { anvilIds, bars, smithables, widgetItems } from '@plugins/skills/smithing/forging-constants'; import { itemIds } from '@engine/world/config/item-ids'; import { Smithable } from '@plugins/skills/smithing/forging-types'; -import { - ItemInteractionAction, - ItemInteractionActionHook -} from '@engine/world/action/item-interaction.action'; import { Player } from '@engine/world/actor/player/player'; -import { findItem } from '@engine/config'; -import { TaskExecutor } from '@engine/world/action'; +import { findItem } from '@engine/config/config-handler'; import { Position } from '@engine/world/position'; +import { logger } from '@runejs/common'; /** * The amount of items the player wants to forge. @@ -23,9 +21,17 @@ let wantedAmount = 0; */ let forgedAmount = 0; -const mapWidgetItemsToFlatArray = (input) => { - const result = []; - smithables.forEach((type) => { +/** + * Get the item ids of all the smithable items, as a flat array. + * + * @param input A two-dimensional map of smithables, keyed by type and then by item id. + * e.g. smithables.get('dagger').get('bronze') + * @returns A flat array of item ids, e.g. [ bronze_dagger_id, iron_dagger_id, ...] + * @remarks This is used to check if the player has the correct item in their inventory. + */ +const mapSmithableItemIdsToFlatArray = (input: Map>) => { + const result: number[] = []; + input.forEach((type) => { type.forEach((smithable) => { result.push(smithable.item.itemId); }); @@ -33,8 +39,19 @@ const mapWidgetItemsToFlatArray = (input) => { return result; }; -const mapToFlatArray = (input) => { - const results = []; +/** + * Flatten a two-dimensional map of Smithables into an array. + * + * TODO (Jameskmonger): this should not be done at runtime! At startup would be one thing, + * but this happens in the `canActivate` method. + * + * @param input A two-dimensional map of smithables, keyed by type and then by item id. + * e.g. smithables.get('dagger').get('bronze') + * @returns A flat array of item ids, e.g. [ bronze_dagger_id, iron_dagger_id, ...] + * @remarks This is used to check if the player has the correct item in their inventory. + */ +const mapSmithablesToFlatArray = (input: Map>) => { + const results: Smithable[] = []; input.forEach((values) => { values.forEach((value) => { results.push(value); @@ -47,10 +64,10 @@ const mapToFlatArray = (input) => { * Lookup a smithable from just an item id. * @param itemId */ -const findSmithableByItemId = (itemId) : Smithable => { - return mapToFlatArray(smithables).find((smithable) => { +const findSmithableByItemId = (itemId: number) : Smithable | null => { + return mapSmithablesToFlatArray(smithables).find((smithable) => { return smithable.item.itemId === itemId; - }); + }) || null; }; /** @@ -59,6 +76,12 @@ const findSmithableByItemId = (itemId) : Smithable => { */ const canActivate = (task: TaskExecutor): boolean => { const { actor, player, actionData } = task.getDetails(); + + if (!player) { + logger.warn('Forging plugin task `canActivate` has no player.'); + return false; + } + const itemId = actionData.itemId; const smithable = findSmithableByItemId(itemId); @@ -70,6 +93,12 @@ const canActivate = (task: TaskExecutor): boolean => { // Check if the player has the level required. if (smithable.level > player.skills.getLevel(Skill.SMITHING)) { const item = findItem(smithable.item.itemId); + + if (item === null) { + logger.warn(`Could not find item for item id ${smithable.item.itemId}`); + return false; + } + player.sendMessage(`You have to be at least level ${smithable.level} to smith ${item.name}s.`, true); return false; } @@ -77,6 +106,12 @@ const canActivate = (task: TaskExecutor): boolean => { // Check if the player has sufficient materials. if (!hasMaterials(player, smithable)) { const bar = findItem(smithable.ingredient.itemId); + + if (bar === null) { + logger.warn(`Could not find ingredient for item id ${smithable.item.itemId}`); + return false; + } + player.sendMessage(`You don't have enough ${bar.name}s.`, true); return false; } @@ -91,11 +126,22 @@ const canActivate = (task: TaskExecutor): boolean => { * @param task * @param taskIteration */ -const activate = (task: TaskExecutor, taskIteration: number): boolean => { +const activate = (task: TaskExecutor, taskIteration: number): boolean | undefined => { const { player, actionData } = task.getDetails(); + + if (!player) { + logger.warn('Forging plugin task `activate` has no player.'); + return false; + } + const itemId = actionData.itemId; const smithable = findSmithableByItemId(itemId); + if (!smithable) { + logger.warn(`Could not find smithable for item id ${itemId}`); + return false; + } + // How many? Quick and dirty. switch (actionData.option) { case 'make' : wantedAmount = 1; break; @@ -162,7 +208,20 @@ const openForgingInterface: itemOnObjectActionHandler = (details) => { } const barLevel = bars.get(item.itemId); + + if (barLevel === undefined) { + logger.warn(`Could not find bar level for item id ${item.itemId}`); + return; + } + const bar = findItem(item.itemId); + + if (bar === null) { + logger.warn(`Could not find bar for item id ${item.itemId}`); + return; + } + + if (barLevel > player.skills.getLevel(Skill.SMITHING)) { player.sendMessage(`You have to be at least level ${barLevel} to smith ${bar.name}s.`, true); return; @@ -175,7 +234,14 @@ const openForgingInterface: itemOnObjectActionHandler = (details) => { slot: 'screen' }); - widgetItems.get(item.itemId).forEach((items, containerId) => { + const barWidgetItems = widgetItems.get(item.itemId); + + if (barWidgetItems === undefined) { + logger.warn(`Could not find bar widget items for item id ${item.itemId}`); + return; + } + + barWidgetItems.forEach((items, containerId) => { items.forEach((smithable, index) => { player.outgoingPackets.sendUpdateSingleWidgetItem({ widgetId: widgets.anvil.widgetId, containerId: containerId @@ -192,13 +258,12 @@ export default { itemIds: [...bars.keys()], objectIds: anvilIds, walkTo: true, - cancelOtherActions: true, handler: openForgingInterface } as ItemOnObjectActionHook, { type: 'item_interaction', - itemIds: [...mapWidgetItemsToFlatArray(smithables)], + itemIds: [...mapSmithableItemIdsToFlatArray(smithables)], options: ['make', 'make-5', 'make-10'], cancelOtherActions: true, task: { diff --git a/src/plugins/skills/smithing/smelting-constants.ts b/src/plugins/skills/smithing/smelting-constants.ts index a74ba8dae..d5ed9adc0 100644 --- a/src/plugins/skills/smithing/smelting-constants.ts +++ b/src/plugins/skills/smithing/smelting-constants.ts @@ -1,4 +1,4 @@ -import { widgets } from '@engine/config'; +import { widgets } from '@engine/config/config-handler'; import { itemIds } from '@engine/world/config/item-ids'; import { Bar, Smeltable } from '@plugins/skills/smithing/smelting-types'; diff --git a/src/plugins/skills/smithing/smelting.plugin.ts b/src/plugins/skills/smithing/smelting.plugin.ts index cedad90f1..02129bf63 100644 --- a/src/plugins/skills/smithing/smelting.plugin.ts +++ b/src/plugins/skills/smithing/smelting.plugin.ts @@ -1,17 +1,17 @@ import { Item } from '@engine/world/items/item'; import { ItemContainer } from '@engine/world/items/item-container'; import { objectIds } from '@engine/world/config/object-ids'; -import { objectInteractionActionHandler, ObjectInteractionAction } from '@engine/world/action/object-interaction.action'; -import { buttonActionHandler, ButtonAction } from '@engine/world/action/button.action'; +import { objectInteractionActionHandler, ObjectInteractionAction } from '@engine/action'; +import { buttonActionHandler, ButtonAction } from '@engine/action'; import { Skill } from '@engine/world/actor/skills'; -import { filestore, loopingEvent } from '@engine/game-server'; import { animationIds } from '@engine/world/config/animation-ids'; import { soundIds } from '@engine/world/config/sound-ids'; import { colors } from '@engine/util/colors'; -import { findItem, widgets } from '@engine/config'; -import { PlayerQuest } from '@engine/config/quest-config'; +import { findItem, widgets } from '@engine/config/config-handler'; import { widgetButtonIds, widgetItems } from '@plugins/skills/smithing/smelting-constants'; import { Bar } from '@plugins/skills/smithing/smelting-types'; +import { loopingEvent } from '@engine/plugins'; +import { logger } from '@runejs/common'; export const openSmeltingInterface: objectInteractionActionHandler = (details) => { @@ -23,7 +23,7 @@ export const openSmeltingInterface: objectInteractionActionHandler = (details) = // We need to tell the widget what the bars actually look like. const loadSmeltingInterface = (details: ObjectInteractionAction) => { - const theKnightsSwordQuest : PlayerQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); + const theKnightsSwordQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); // Send the items to the widget. widgetItems.forEach((item) => { details.player.outgoingPackets.setItemOnWidget(widgets.furnace.widgetId, item.slot.modelId, item.bar.barId, 125); @@ -32,6 +32,9 @@ const loadSmeltingInterface = (details: ObjectInteractionAction) => { } else { details.player.modifyWidget(widgets.furnace.widgetId, { childId: item.slot.titleId, textColor: colors.black }); } + + + // TODO (Jameskmonger) I don't think that this logic is correct.. it targets all items, not just those related to the quest. // Check if the player has completed 'The Knight's Sword' quest, even if the level is okay. if (item.bar.quest !== undefined && (theKnightsSwordQuest == undefined || theKnightsSwordQuest.complete)) { details.player.modifyWidget(widgets.furnace.widgetId, { childId: item.slot.titleId, textColor: colors.red }); @@ -46,7 +49,9 @@ const hasIngredients = (details: ButtonAction, ingredients: Item[], inventory: I ingredients.forEach((item: Item) => { const itemIndex = inventory.findIndex(item); if (itemIndex === -1 || inventory.amountInStack(itemIndex) < item.amount) { - details.player.sendMessage(`You don't have enough ${findItem(item.itemId).name.toLowerCase()}.`, true); + const itemName = findItem(item.itemId)?.name || ''; + + details.player.sendMessage(`You don't have enough ${itemName.toLowerCase()}.`, true); loop.cancel(); return; } @@ -59,7 +64,8 @@ const canSmelt = (details: ButtonAction, bar: Bar): boolean => { const smeltProduct = (details: ButtonAction, bar: Bar, count: number) => { - const theKnightsSwordQuest : PlayerQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); + // TODO (Jameskmonger) I don't think that this logic is correct.. it targets all items, not just those related to the quest. + const theKnightsSwordQuest = details.player.quests.find(quest => quest.questId === 'theKnightsSword'); if (bar.quest !== undefined && (theKnightsSwordQuest == undefined || theKnightsSwordQuest.complete)) { details.player.sendMessage(`You need to complete The Knight's Sword quest first.`, true); return; @@ -67,7 +73,8 @@ const smeltProduct = (details: ButtonAction, bar: Bar, count: number) => { // Check if the player has the required smithing level. if (!canSmelt(details, bar)) { - details.player.sendMessage(`You need a smithing level of ${bar.requiredLevel} to smelt ${findItem(bar.barId).name.toLowerCase()}s.`, true); + const barName = findItem(bar.barId)?.name || ''; + details.player.sendMessage(`You need a smithing level of ${bar.requiredLevel} to smelt ${barName.toLowerCase()}s.`, true); return; } @@ -116,6 +123,11 @@ export const buttonClicked : buttonActionHandler = (details) => { const product = widgetButtonIds.get(details.buttonId); + if (!product) { + logger.warn(`No smeltable product found for buttonId ${details.buttonId}.`); + return; + } + details.player.interfaceState.closeAllSlots(); if (!product.takesInput) { diff --git a/src/plugins/skills/woodcutting/chance.ts b/src/plugins/skills/woodcutting/chance.ts new file mode 100644 index 000000000..ef7a5f31c --- /dev/null +++ b/src/plugins/skills/woodcutting/chance.ts @@ -0,0 +1,23 @@ +import { randomBetween } from '@engine/util'; +import { IHarvestable } from '@engine/world/config'; + +/** + * Roll a random number between 0 and 255 and compare it to the percent needed to cut the tree. + * + * @param tree The tree to cut + * @param toolLevel The level of the axe being used + * @param woodcuttingLevel The player's woodcutting level + * + * @returns True if the tree was successfully cut, false otherwise + */ +export const canCut = ( + tree: IHarvestable, + toolLevel: number, + woodcuttingLevel: number +): boolean => { + const successChance = randomBetween(0, 255); + + const percentNeeded = + tree.baseChance + toolLevel + woodcuttingLevel; + return successChance <= percentNeeded; +}; diff --git a/src/plugins/skills/woodcutting/index.ts b/src/plugins/skills/woodcutting/index.ts new file mode 100644 index 000000000..12bd82cf8 --- /dev/null +++ b/src/plugins/skills/woodcutting/index.ts @@ -0,0 +1,27 @@ +import { + ObjectInteractionActionHook, +} from '@engine/action'; +import { getTreeIds } from '@engine/world/config/harvestable-object'; +import { runWoodcuttingTask } from './woodcutting-task'; + +/** + * Woodcutting plugin + * + * This uses the task system to schedule actions. + */ +export default { + pluginId: 'rs:woodcutting', + hooks: [ + /** + * "Chop down" / "chop" object interaction hook. + */ + { + type: 'object_interaction', + options: [ 'chop down', 'chop' ], + objectIds: getTreeIds(), + handler: ({ player, object }) => { + runWoodcuttingTask(player, object); + } + } as ObjectInteractionActionHook + ] +}; diff --git a/src/plugins/skills/woodcutting/woodcutting-task.ts b/src/plugins/skills/woodcutting/woodcutting-task.ts new file mode 100644 index 000000000..15c8fae1f --- /dev/null +++ b/src/plugins/skills/woodcutting/woodcutting-task.ts @@ -0,0 +1,192 @@ +import { Skill } from '@engine/world/actor/skills'; +import { canInitiateHarvest } from '@engine/world/skill-util/harvest-skill'; +import { getTreeFromHealthy, IHarvestable } from '@engine/world/config/harvestable-object'; +import { randomBetween } from '@engine/util/num'; +import { colorText } from '@engine/util/strings'; +import { colors } from '@engine/util/colors'; +import { rollBirdsNestType } from '@engine/world/skill-util/harvest-roll'; +import { soundIds } from '@engine/world/config/sound-ids'; +import { findItem, findObject } from '@engine/config/config-handler'; +import { activeWorld } from '@engine/world'; +import { canCut } from './chance'; +import { ActorLandscapeObjectInteractionTask } from '@engine/task/impl'; +import { Player } from '@engine/world/actor'; +import { LandscapeObject } from '@runejs/filestore'; +import { logger } from '@runejs/common'; + +class WoodcuttingTask extends ActorLandscapeObjectInteractionTask { + /** + * The tree being cut down. + */ + private treeInfo: IHarvestable; + + /** + * The number of ticks that `execute` has been called inside this task. + */ + private elapsedTicks = 0; + + /** + * Create a new woodcutting task. + * + * @param player The player that is attempting to cut down the tree. + * @param landscapeObject The object that represents the tree. + * @param sizeX The size of the tree in x axis. + * @param sizeY The size of the tree in y axis. + */ + constructor( + player: Player, + landscapeObject: LandscapeObject, + sizeX: number, + sizeY: number + ) { + super( + player, + landscapeObject, + sizeX, + sizeY + ); + + if (!landscapeObject) { + this.stop(); + return; + } + + this.treeInfo = getTreeFromHealthy(landscapeObject.objectId); + if (!this.treeInfo) { + this.stop(); + return; + } + } + + /** + * Execute the main woodcutting task loop. This method is called every game tick until the task is completed. + * + * As this task extends {@link ActorLandscapeObjectInteractionTask}, it's important that the + * `super.execute` method is called at the start of this method. + * + * The base `execute` performs a number of checks that allow this task to function healthily. + */ + public execute(): void { + super.execute(); + + if (!this.isActive || !this.landscapeObject) { + return; + } + + // store the tick count before incrementing so we don't need to keep track of it in all the separate branches + const taskIteration = this.elapsedTicks++; + + const tool = canInitiateHarvest(this.actor, this.treeInfo, Skill.WOODCUTTING); + + if (!tool) { + this.stop(); + return; + } + + if(taskIteration === 0) { + this.actor.sendMessage('You swing your axe at the tree.'); + this.actor.face(this.landscapeObjectPosition); + this.actor.playAnimation(tool.animation); + return; + } + + // play a random axe sound at the correct time + if(taskIteration % 3 !== 0) { + if(taskIteration % 1 === 0) { + const randomSoundIdx = Math.floor(Math.random() * soundIds.axeSwing.length); + this.actor.playSound(soundIds.axeSwing[randomSoundIdx], 7, 0); + } + return; + } + + // Get tool level, and set it to 2 if the tool is an iron hatchet or iron pickaxe axe + // TODO why is this set to 2? Was ported from the old code + let toolLevel = tool.level - 1; + if(tool.itemId === 1349 || tool.itemId === 1267) { + toolLevel = 2; + } + + // roll for success + const succeeds = canCut(this.treeInfo, toolLevel, this.actor.skills.woodcutting.level); + if(!succeeds) { + return; + } + + const logItem = findObject(this.treeInfo.itemId); + + if(!logItem) { + logger.error(`Could not find log item with id ${this.treeInfo.itemId}`); + this.actor.sendMessage('Sorry, an error occurred. Please report this to a developer.'); + this.stop(); + return; + } + + const targetName = (logItem.name || '').toLowerCase(); + + // if player doesn't have space in inventory, stop the task + if(!this.actor.inventory.hasSpace()) { + this.actor.sendMessage(`Your inventory is too full to hold any more ${targetName}.`, true); + this.actor.playSound(soundIds.inventoryFull); + this.stop(); + return; + } + + const itemToAdd = this.treeInfo.itemId; + const roll = randomBetween(1, 256); + // roll for bird nest chance + if(roll === 1) { + this.actor.sendMessage(colorText(`A bird's nest falls out of the tree.`, colors.red)); + activeWorld.globalInstance.spawnWorldItem(rollBirdsNestType(), this.actor.position, + { owner: this.actor || null, expires: 300 }); + } else { // Standard log chopper + this.actor.sendMessage(`You manage to chop some ${targetName}.`); + this.actor.giveItem(itemToAdd); + } + + this.actor.skills.woodcutting.addExp(this.treeInfo.experience); + + // check if the tree should be broken + if(randomBetween(0, 100) <= this.treeInfo.break) { + // TODO (Jameskmonger) is this the correct sound? + this.actor.playSound(soundIds.oreDepeleted); + + const brokenTreeId = this.treeInfo.objects.get(this.landscapeObject.objectId); + + if (brokenTreeId !== undefined) { + this.actor.instance.replaceGameObject(brokenTreeId, + this.landscapeObject, randomBetween(this.treeInfo.respawnLow, this.treeInfo.respawnHigh)); + } else { + logger.error(`Could not find broken tree id for tree id ${this.landscapeObject.objectId}`); + } + + this.stop(); + return; + } + + this.actor.playAnimation(tool.animation); + + } + + /** + * This method is called when the task stops. + */ + public onStop(): void { + super.onStop(); + + this.actor.stopAnimation(); + } +} + +export function runWoodcuttingTask(player: Player, landscapeObject: LandscapeObject): void { + const objectConfig = findObject(landscapeObject.objectId); + + if (!objectConfig) { + logger.warn(`Player ${player.username} attempted to run a woodcutting task on an invalid object (id: ${landscapeObject.objectId})`); + return; + } + + const sizeX = objectConfig.rendering.sizeX; + const sizeY = objectConfig.rendering.sizeY; + + player.enqueueTask(WoodcuttingTask, [ landscapeObject, sizeX, sizeY ]); +} diff --git a/src/plugins/skills/woodcutting/woodcutting.plugin.ts b/src/plugins/skills/woodcutting/woodcutting.plugin.ts deleted file mode 100644 index dcd847563..000000000 --- a/src/plugins/skills/woodcutting/woodcutting.plugin.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { - ObjectInteractionAction, - ObjectInteractionActionHook -} from '@engine/world/action/object-interaction.action'; -import { Skill } from '@engine/world/actor/skills'; -import { canInitiateHarvest } from '@engine/world/skill-util/harvest-skill'; -import { getTreeFromHealthy, getTreeIds, IHarvestable } from '@engine/world/config/harvestable-object'; -import { randomBetween } from '@engine/util/num'; -import { colorText } from '@engine/util/strings'; -import { colors } from '@engine/util/colors'; -import { rollBirdsNestType } from '@engine/world/skill-util/harvest-roll'; -import { world } from '@engine/game-server'; -import { soundIds } from '@engine/world/config/sound-ids'; -import { Axe, getAxe, HarvestTool } from '@engine/world/config/harvest-tool'; -import { TaskExecutor } from '@engine/world/action'; -import { findItem } from '@engine/config'; - - -const canActivate = (task: TaskExecutor, taskIteration: number): boolean => { - const { actor, actionData: { position, object } } = task; - const tree = getTreeFromHealthy(object.objectId); - - if(!tree) { - return false; - } - - const { type: { player }, isPlayer } = actor; - - const tool = isPlayer ? canInitiateHarvest(player, tree, Skill.WOODCUTTING) : getAxe(Axe.STEEL); - - if(!tool) { - return false; - } - - task.session.tool = tool; - task.session.tree = tree; - - if(taskIteration === 0) { - // First run - - player?.sendMessage('You swing your axe at the tree.'); - - actor.face(position); - actor.playAnimation(tool.animation); - } - - return true; -}; - - -const activate = (task: TaskExecutor, taskIteration: number): boolean => { - const { actor, player, actionData, session } = task.getDetails(); - const { position: objectPosition, object: actionObject } = actionData; - const tree: IHarvestable = session.tree; - const tool: HarvestTool = session.tool; - - // Cancel if the actor no longer has their tool or level requirements. - if(!tool || !tree) { - return false; - } - - // Grab the tree manually every loop so that we can make sure it's still alive. - const { object } = world.findObjectAtLocation(actor, actionObject.objectId, objectPosition); - - if(!object) { - // Tree has been chopped down, cancel. - return false; - } - - // Check if the amount of ticks passed equal the tools pulses. - if(taskIteration % 3 === 0 && taskIteration != 0) { - const successChance = randomBetween(0, 255); - - let toolLevel = tool.level - 1; - if(tool.itemId === 1349 || tool.itemId === 1267) { - toolLevel = 2; - } - - const percentNeeded = tree.baseChance + toolLevel + actor.skills.woodcutting.level; - if(successChance <= percentNeeded) { - const targetName: string = findItem(tree.itemId).name.toLowerCase(); - - if(actor.inventory.hasSpace()) { - const itemToAdd = tree.itemId; - const roll = randomBetween(1, 256); - - if(roll === 1) { // Bird nest chance - player?.sendMessage(colorText(`A bird's nest falls out of the tree.`, colors.red)); - world.globalInstance.spawnWorldItem(rollBirdsNestType(), actor.position, - { owner: player || null, expires: 300 }); - } else { // Standard log chopper - player?.sendMessage(`You manage to chop some ${targetName}.`); - actor.giveItem(itemToAdd); - } - - player?.skills.woodcutting.addExp(tree.experience); - - if(randomBetween(0, 100) <= tree.break) { - player?.playSound(soundIds.oreDepeleted); - actor.instance.replaceGameObject(tree.objects.get(actionObject.objectId), - object, randomBetween(tree.respawnLow, tree.respawnHigh)); - return false; - } - } else { - player?.sendMessage( - `Your inventory is too full to hold any more ${targetName}.`, true); - player?.playSound(soundIds.inventoryFull); - return false; - } - } - } else { - if(taskIteration % 1 === 0 && taskIteration !== 0) { - const randomSoundIdx = Math.floor(Math.random() * soundIds.axeSwing.length); - player?.playSound(soundIds.axeSwing[randomSoundIdx], 7, 0); - } - } - - if(taskIteration % 3 === 0 && taskIteration !== 0) { - actor.playAnimation(tool.animation); - } - - return true; -}; - -const onComplete = (task: TaskExecutor): void => { - task.actor.stopAnimation(); -}; - - -export default { - pluginId: 'rs:woodcutting', - hooks: [ - { - type: 'object_interaction', - options: [ 'chop down', 'chop' ], - objectIds: getTreeIds(), - strength: 'normal', - task: { - canActivate, - activate, - onComplete, - interval: 1 - } - } as ObjectInteractionActionHook - ] -}; diff --git a/src/game-engine/config/server-config.ts b/src/server/game/game-server-config.ts similarity index 84% rename from src/game-engine/config/server-config.ts rename to src/server/game/game-server-config.ts index 00220e97e..271a57d91 100644 --- a/src/game-engine/config/server-config.ts +++ b/src/server/game/game-server-config.ts @@ -1,8 +1,9 @@ -export interface ServerConfig { +export interface GameServerConfig { rsaMod: string; rsaExp: string; host: string; port: number; + encryptionEnabled: boolean; loginServerHost: string; loginServerPort: number; updateServerHost: string; diff --git a/src/game-engine/net/server/game-server.ts b/src/server/game/game-server-connection.ts similarity index 69% rename from src/game-engine/net/server/game-server.ts rename to src/server/game/game-server-connection.ts index fba1e7d16..d61ac1659 100644 --- a/src/game-engine/net/server/game-server.ts +++ b/src/server/game/game-server-connection.ts @@ -1,17 +1,17 @@ -import { logger } from '@runejs/core'; -import { ConnectionStatus, SocketServer } from '@runejs/core/net'; -import { ByteBuffer } from '@runejs/core/buffer'; import { Socket } from 'net'; -import { ServerGateway } from '@engine/net/server/server-gateway'; -import { handlePacket, incomingPackets } from '@engine/net/inbound-packets'; -import { Player } from '@engine/world/actor/player/player'; + +import { logger } from '@runejs/common'; +import { ByteBuffer } from '@runejs/common'; + +import { handlePacket, incomingPackets } from '@engine/net'; +import { Player } from '@engine/world/actor'; export class GameServerConnection { - private activePacketId: number = null; - private activePacketSize: number = null; - private activeBuffer: ByteBuffer; + private activePacketId: number | null = null; + private activePacketSize: number | null = null; + private activeBuffer: ByteBuffer | null; public constructor(private readonly clientSocket: Socket, private readonly player: Player) { @@ -19,7 +19,12 @@ export class GameServerConnection { public decodeMessage(buffer?: ByteBuffer): void | Promise { if(!this.activeBuffer) { - this.activeBuffer = buffer; + if (!buffer) { + logger.error(`No buffer provided to decodeMessage.`); + return; + } else { + this.activeBuffer = buffer; + } } else if(buffer) { const readable = this.activeBuffer.readable; const newBuffer = new ByteBuffer(readable + buffer.length); @@ -43,7 +48,7 @@ export class GameServerConnection { return; } - this.activePacketId = this.activeBuffer.get('BYTE', 'UNSIGNED'); + this.activePacketId = this.activeBuffer.get('byte', 'u'); this.activePacketId = (this.activePacketId - inCipher.rand()) & 0xff; const incomingPacket = incomingPackets.get(this.activePacketId); if(incomingPacket) { @@ -59,7 +64,7 @@ export class GameServerConnection { return; } - this.activePacketSize = this.activeBuffer.get('BYTE', 'UNSIGNED'); + this.activePacketSize = this.activeBuffer.get('byte', 'u'); } // Packet has no set size @@ -78,16 +83,17 @@ export class GameServerConnection { } // read packet data - let packetData = null; + let packetData: ByteBuffer | null = null; if(this.activePacketSize !== 0) { packetData = new ByteBuffer(this.activePacketSize); - this.activeBuffer.copy(packetData, 0, this.activeBuffer.readerIndex, this.activeBuffer.readerIndex + this.activePacketSize); + this.activeBuffer.copy(packetData, 0, this.activeBuffer.readerIndex, + this.activeBuffer.readerIndex + this.activePacketSize); this.activeBuffer.readerIndex += this.activePacketSize; } - if(!handlePacket(this.player, this.activePacketId, this.activePacketSize, packetData)) { - logger.error(`Player packets out of sync for ${this.player.username}, resetting packet buffer...`); - logger.error(`If you're seeing this, there's a packet that needs fixing. :)`); + if(packetData && !handlePacket(this.player, this.activePacketId, this.activePacketSize, packetData)) { + logger.error(`Player packets out of sync for ${this.player.username}, resetting packet buffer...`, + `If you're seeing this, there's a packet that needs fixing. :)`); clearBuffer = true; } @@ -113,8 +119,3 @@ export class GameServerConnection { } } - -export const openGameServer = (host: string, port: number): void => - SocketServer.launch( - 'Game Server', - host, port, socket => new ServerGateway(socket)); diff --git a/src/server/game/game-server.ts b/src/server/game/game-server.ts new file mode 100644 index 000000000..e858dafa9 --- /dev/null +++ b/src/server/game/game-server.ts @@ -0,0 +1,60 @@ +import { logger } from '@runejs/common'; +import { parseServerConfig, SocketServer } from '@runejs/common/net'; +import { Filestore } from '@runejs/filestore'; + +import { activateGameWorld } from '@engine/world'; +import { loadCoreConfigurations, loadGameConfigurations, xteaRegions } from '@engine/config'; +import { loadPackets } from '@engine/net'; +import { watchForChanges, watchSource } from '@engine/util'; +import { GatewayServer } from '@server/gateway'; +import { GameServerConfig } from '@server/game'; + + +/** + * The singleton instance containing the server's active configuration settings. + */ +export let serverConfig: GameServerConfig; + + +/** + * The singleton instance referencing the game's asset file store. + */ +export let filestore: Filestore; + + +export const openGatewayServer = (host: string, port: number): void => { + SocketServer.launch( + 'Game Gateway Server', + host, port, socket => new GatewayServer(socket)); +}; + + +/** + * Configures the game server, parses the asset file store, initializes the game world, + * and finally spins up the game server itself. + */ +export async function launchGameServer(): Promise { + serverConfig = parseServerConfig(); + + if(!serverConfig) { + logger.error('Unable to start server due to missing or invalid server configuration.'); + return; + } + + await loadCoreConfigurations(); + filestore = new Filestore('cache', { xteas: xteaRegions }); + + await loadGameConfigurations(); + await loadPackets(); + + const world = await activateGameWorld(); + + if(process.argv.indexOf('-fakePlayers') !== -1) { + world.generateFakePlayers(); + } + + openGatewayServer(serverConfig.host, serverConfig.port); + + watchSource('src/').subscribe(() => world.saveOnlinePlayers()); + watchForChanges('dist/plugins/', /[/\\]plugins[/\\]/); +} diff --git a/src/server/game/index.ts b/src/server/game/index.ts new file mode 100644 index 000000000..28138dd81 --- /dev/null +++ b/src/server/game/index.ts @@ -0,0 +1,3 @@ +export * from './game-server'; +export * from './game-server-config'; +export * from './game-server-connection'; diff --git a/src/game-engine/net/server/server-gateway.ts b/src/server/gateway/gateway-server.ts similarity index 82% rename from src/game-engine/net/server/server-gateway.ts rename to src/server/gateway/gateway-server.ts index d4ce879f3..32742ed1a 100644 --- a/src/game-engine/net/server/server-gateway.ts +++ b/src/server/gateway/gateway-server.ts @@ -1,20 +1,22 @@ -import { logger } from '@runejs/core'; -import { LoginResponseCode } from '@runejs/login-server'; -import { ByteBuffer } from '@runejs/core/buffer'; -import { parseServerConfig, SocketServer } from '@runejs/core/net'; import { createConnection, Socket } from 'net'; -import { GameServerConnection } from '@engine/net/server/game-server'; -import { ServerConfig } from '@engine/config/server-config'; -import { Isaac } from '@engine/net/isaac'; -import { Player } from '@engine/world/actor/player/player'; -import { world } from '@engine/game-server'; -const serverConfig = parseServerConfig(); +import { logger } from '@runejs/common'; +import { ByteBuffer } from '@runejs/common'; +import { parseServerConfig, SocketServer } from '@runejs/common/net'; +import { LoginResponseCode } from '@runejs/login-server'; + +import { Isaac } from '@engine/net'; +import { activeWorld } from '@engine/world'; +import { Player } from '@engine/world/actor'; +import { GameServerConfig, GameServerConnection } from '@server/game'; + + +const serverConfig = parseServerConfig(); export type ServerType = 'game_server' | 'login_server' | 'update_server'; -export class ServerGateway extends SocketServer { +export class GatewayServer extends SocketServer { private serverType: ServerType; private gameServerConnection: GameServerConnection; @@ -36,7 +38,7 @@ export class ServerGateway extends SocketServer { // Here we find out what kind of connection the client is making - game, or update server? // If game - they'll need to pass through the login server to authenticate first! - const packetId = buffer.get('BYTE', 'UNSIGNED'); + const packetId = buffer.get('byte', 'u'); if(packetId === 15) { this.serverType = 'update_server'; @@ -60,7 +62,9 @@ export class ServerGateway extends SocketServer { host: serverConfig.loginServerHost, port: serverConfig.loginServerPort }); - this.loginServerSocket.on('data', data => this.parseLoginServerResponse(new ByteBuffer(data))); + this.loginServerSocket.on('data', data => { + this.parseLoginServerResponse(new ByteBuffer(data)); + }); this.loginServerSocket.on('end', () => { logger.error(`Login server error.`); }); @@ -95,7 +99,7 @@ export class ServerGateway extends SocketServer { this.gameServerConnection?.connectionDestroyed(); } - private parseLoginServerResponse(buffer: ByteBuffer): void { + private async parseLoginServerResponse(buffer: ByteBuffer): Promise { if(!this.serverKey) { // Login handshake response const handshakeResponseCode = buffer.get('byte'); @@ -116,19 +120,20 @@ export class ServerGateway extends SocketServer { const passwordHash = buffer.getString(); const lowDetail = buffer.get('byte') === 1; - if(world.playerOnline(username)) { + if(activeWorld.playerOnline(username)) { // Player is already logged in! // @TODO move to login server buffer = new ByteBuffer(1); buffer.put(LoginResponseCode.ALREADY_LOGGED_IN); } else { this.serverType = 'game_server'; - this.createPlayer([ clientKey1, clientKey2 ], gameClientId, username, passwordHash, lowDetail ? 'low' : 'high'); + await this.createPlayer([ clientKey1, clientKey2 ], + gameClientId, username, passwordHash, lowDetail ? 'low' : 'high'); return; } } catch(e) { - logger.error(e); this.gameServerConnection?.closeSocket(); + logger.error(e); } } } @@ -143,7 +148,10 @@ export class ServerGateway extends SocketServer { passwordHash: string, detail: 'high' | 'low'): Promise { const sessionKey: number[] = [ - Number(clientKeys[0]), Number(clientKeys[1]), Number(this.serverKey >> BigInt(32)), Number(this.serverKey) + Number(clientKeys[0]), + Number(clientKeys[1]), + Number(this.serverKey >> BigInt(32)), + Number(this.serverKey) ]; const inCipher = new Isaac(sessionKey); @@ -154,11 +162,12 @@ export class ServerGateway extends SocketServer { const outCipher = new Isaac(sessionKey); - const player = new Player(this.clientSocket, inCipher, outCipher, gameClientId, username, passwordHash, detail === 'low'); + const player = new Player(this.clientSocket, inCipher, outCipher, gameClientId, + username, passwordHash, detail === 'low'); this.gameServerConnection = new GameServerConnection(this.clientSocket, player); - world.registerPlayer(player); + activeWorld.registerPlayer(player); const outputBuffer = new ByteBuffer(6); diff --git a/src/server/gateway/index.ts b/src/server/gateway/index.ts new file mode 100644 index 000000000..6aaaa5941 --- /dev/null +++ b/src/server/gateway/index.ts @@ -0,0 +1 @@ +export * from './gateway-server'; diff --git a/src/server/index.ts b/src/server/index.ts new file mode 100644 index 000000000..bde5e81d3 --- /dev/null +++ b/src/server/index.ts @@ -0,0 +1 @@ +export * from './runner'; diff --git a/src/server/runner.ts b/src/server/runner.ts new file mode 100644 index 000000000..5300f5611 --- /dev/null +++ b/src/server/runner.ts @@ -0,0 +1,51 @@ +import 'source-map-support/register'; + +import { logger } from '@runejs/common'; +import { launchLoginServer } from '@runejs/login-server'; +import { launchUpdateServer } from '@runejs/update-server'; +import { launchGameServer } from '@server/game'; +import { initErrorHandling } from '@engine/util'; +import { activeWorld } from '@engine/world'; + + +const shutdownEvents = [ + 'SIGHUP', 'SIGINT', 'SIGQUIT', + 'SIGILL', 'SIGTRAP', 'SIGABRT', + 'SIGBUS', 'SIGFPE', 'SIGUSR1', + 'SIGSEGV', 'SIGUSR2', 'SIGTERM' +]; + +let running: boolean = true; +let type: 'game' | 'login' | 'update' = 'game'; + +if(process.argv.indexOf('-login') !== -1) { + type = 'login'; +} else if(process.argv.indexOf('-update') !== -1) { + type = 'update'; +} + +shutdownEvents.forEach(signal => process.on(signal as any, () => { + if(!running) { + return; + } + running = false; + + logger.warn(`${signal} received.`); + + if(type === 'game') { + activeWorld?.shutdown(); + } + + logger.info(`${type.charAt(0).toUpperCase()}${type.substring(1)} Server shutting down...`); + process.exit(0); +})); + +initErrorHandling(); + +if(type === 'game') { + launchGameServer(); +} else if(type === 'login') { + launchLoginServer(); +} else if(type === 'update') { + launchUpdateServer(); +} diff --git a/tsconfig.json b/tsconfig.json index f450760f9..9374d8311 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,14 +11,21 @@ "resolveJsonModule": true, "allowSyntheticDefaultImports": true, "sourceMap": true, + "strict": false, + "strictBindCallApply": true, + "strictFunctionTypes": false, + "strictNullChecks": true, + "strictPropertyInitialization": false, "baseUrl": ".", "allowJs": true, "outDir": "./dist/", "paths": { - "@engine/*": ["src/game-engine/*"], + "@engine/*": ["src/engine/*"], + "@server/*": ["src/server/*"], "@plugins/*": ["src/plugins/*"] }, "types": [ + "jest", "node" ], "lib": [ @@ -31,10 +38,8 @@ "include": [ "src/**/*.js", "src/**/*.ts", - "src/**/*.tsx", - "src/**/*.vue", - "tests/**/*.ts", - "tests/**/*.tsx" + "tests/**/*.js", + "tests/**/*.ts" ], "exclude": [ "node_modules"