diff --git a/.env.example b/.env.example
index cd3aa94..34f4d49 100644
--- a/.env.example
+++ b/.env.example
@@ -7,4 +7,6 @@ BASIC_USERNAME=root
BASIC_PASSWORD=secret
SENTRY_ENABLED=true
SENTRY_PROJECT_ID=projectId
-SENTRY_KEY=key
\ No newline at end of file
+SENTRY_KEY=key
+FACEBOOK_APP_ID=appId
+GOOGLE_CLIENT_ID=clientId
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac2f6b8..3b8376b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,58 @@
# ๐ LIST OF CHANGES FOR WEREWOLVES ASSISTANT API
+## 0.11.0 (2021-04-30)
+
+### ๐ New features
+
+* [#137](https://github.com/antoinezanardi/werewolves-assistant-api/issues/137) - `position` for each player.
+* [#138](https://github.com/antoinezanardi/werewolves-assistant-api/issues/138) - Facebook authentication.
+* [#139](https://github.com/antoinezanardi/werewolves-assistant-api/issues/139) - Google authentication.
+* [#141](https://github.com/antoinezanardi/werewolves-assistant-api/issues/141) - Fox role.
+* [#142](https://github.com/antoinezanardi/werewolves-assistant-api/issues/142) - Bear Tamer role.
+* [#143](https://github.com/antoinezanardi/werewolves-assistant-api/issues/143) - Hidden game repartition option.
+* [#144](https://github.com/antoinezanardi/werewolves-assistant-api/issues/144) - Role revealed on death option.
+* [#145](https://github.com/antoinezanardi/werewolves-assistant-api/issues/145) - Seer see exact role option.
+* [#146](https://github.com/antoinezanardi/werewolves-assistant-api/issues/146) - Guard can protect twice option.
+* [#147](https://github.com/antoinezanardi/werewolves-assistant-api/issues/147) - Fox not powerless if he misses a werewolf option.
+* [#148](https://github.com/antoinezanardi/werewolves-assistant-api/issues/148) - Bear Tamer growls if he is infected option.
+* [#149](https://github.com/antoinezanardi/werewolves-assistant-api/issues/149) - Number of vote requests for Stuttering Judge option.
+* [#150](https://github.com/antoinezanardi/werewolves-assistant-api/issues/150) - Time for the Sheriff to be elected option.
+* [#151](https://github.com/antoinezanardi/werewolves-assistant-api/issues/151) - Thief not obliged to choose between werewolves cards option.
+* [#152](https://github.com/antoinezanardi/werewolves-assistant-api/issues/152) - Wild Child transformation is revealed option.
+* [#153](https://github.com/antoinezanardi/werewolves-assistant-api/issues/153) - Dog Wolf chosen side is revealed option.
+* [#154](https://github.com/antoinezanardi/werewolves-assistant-api/issues/154) - Big Bad Wolf not powerless if one werewolf dies option.
+* [#155](https://github.com/antoinezanardi/werewolves-assistant-api/issues/155) - White Werewolf waking up interval option.
+* [#156](https://github.com/antoinezanardi/werewolves-assistant-api/issues/156) - Number of charmed people per night by Pied Piper option.
+* [#157](https://github.com/antoinezanardi/werewolves-assistant-api/issues/157) - Pied Piper not powerless if infected option.
+* [#158](https://github.com/antoinezanardi/werewolves-assistant-api/issues/158) - Lives count for the Ancient option.
+* [#159](https://github.com/antoinezanardi/werewolves-assistant-api/issues/159) - Ancient doesn't make all villagers powerless if murdered from them option.
+* [#160](https://github.com/antoinezanardi/werewolves-assistant-api/issues/160) - Number of additional cards for Thief option.
+* [#161](https://github.com/antoinezanardi/werewolves-assistant-api/issues/161) - Rusty Sword Knight role.
+
+### ๐ Enhancements
+
+* [#162](https://github.com/antoinezanardi/werewolves-assistant-api/issues/162) - Role types.
+
+### โป๏ธ Refactoring
+
+* [#140](https://github.com/antoinezanardi/werewolves-assistant-api/issues/140) - Extend token's lifetime to infinity.
+
+### ๐ฆ Packages
+
+* `axios` installed with version `0.21.1`.
+* `@sentry/node` updated to version `6.3.5`.
+* `apidoc` updated to version `0.26.0`.
+* `chai` updated to version `4.3.4`.
+* `eslint` updated to version `7.25.0`.
+* `express-validator` updated to version `6.10.1`.
+* `migrate-mongo` updated to version `8.2.2`.
+* `mocha` updated to version `8.3.2`.
+* `mongoose` updated to version `5.12.6`.
+* `qs` updated to version `6.10.1`.
+* `validator` updated to version `13.6.0`.
+
+---
+
## 0.10.0 (2021-03-03)
### ๐ New features
diff --git a/README.md b/README.md
index 197bc45..89d9c03 100644
--- a/README.md
+++ b/README.md
@@ -38,13 +38,13 @@ Two versions are available for testing this API:
๐ง **Sandbox API** _(Base URL: https://sandbox.werewolves-assistant-api.antoinezanardi.fr)_
-**Sandbox API** may contains some bugs and unexpected behaviors as its purpose is to test new features before deploying on **main API**.
+**Sandbox API** may contain some bugs and unexpected behaviors as its purpose is to test new features before deploying on **main API**.
Both APIs are running on a server with the following configuration:
- **OS**: `Debian GNU/Linux 10 (buster)`
-- **NodeJS**: `v14.15.4`
-- **NPM**: `v7.5.2`
-- **MongoDB shell version**: `v4.4.3`
+- **NodeJS**: `v14.16.1`
+- **NPM**: `v6.14.12`
+- **MongoDB shell version**: `v4.4.5`
The MongoDB database is protected under username and password authentication.
@@ -52,7 +52,7 @@ The MongoDB database is protected under username and password authentication.
## ๐ Roles available
-On this current version [![GitHub release](https://img.shields.io/github/release/antoinezanardi/werewolves-assistant-api.svg)](https://GitHub.com/antoinezanardi/werewolves-assistant-api/releases/), **24 different roles** are available to play:
+On this current version [![GitHub release](https://img.shields.io/github/release/antoinezanardi/werewolves-assistant-api.svg)](https://GitHub.com/antoinezanardi/werewolves-assistant-api/releases/), **27 different roles** are available to play:
- ** The Werewolf**
- ** The Big Bad Wolf**
@@ -71,7 +71,10 @@ On this current version [![GitHub release](https://img.shields.io/github/release
- ** The Idiot**
- ** The Two Sisters**
- ** The Three Brothers**
+- ** The Fox**
+- ** The Bear Tamer**
- ** The Stuttering Judge**
+- ** The Rusty Sword Knight**
- ** The Wild Child**
- ** The Dog-Wolf**
- ** The Thief**
@@ -137,6 +140,10 @@ Complete list of all enabled rules is available in the **[.eslintrc.js file](htt
- _**Not required**_
* **SENTRY_KEY**: Sentry secret key.
- _**Not required**_
+ * **FACEBOOK_APP_ID**: Facebook application ID if you want to enable Facebook authentication.
+ - _**Not Required**_
+ * **GOOGLE_CLIENT_ID**: Google client ID if you want to enable Google authentication.
+ - _**Not Required**_
## ๐ Let's go
diff --git a/app.js b/app.js
index abb9722..6932b16 100644
--- a/app.js
+++ b/app.js
@@ -8,6 +8,7 @@ const cors = require("cors");
const Config = require("./config");
const { sendError, generateError } = require("./src/helpers/functions/Error");
const { connect: connectDatabase } = require("./src/helpers/functions/Mongoose");
+const routes = require("./src/routes");
if (Config.sentry.enabled) {
const Sentry = require("@sentry/node");
@@ -15,7 +16,9 @@ if (Config.sentry.enabled) {
}
console.log("Starting the application...");
connectDatabase().then(() => {
- console.log("โ
Connected to database.");
+ if (Config.app.nodeEnv !== "test") {
+ console.log("โ
Connected to database.");
+ }
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors({ origin: "*" }));
@@ -27,13 +30,13 @@ connectDatabase().then(() => {
next();
}
});
- const routes = require("./src/routes");
routes(app);
app.listen(Config.app.port);
- console.log(`${bold("๐บ Werewolves Assistant API")} server started on port ${bold.blue(Config.app.port)} and running on database ${bold.green(Config.db.name)}.`);
- console.log(`${bold("๐ API Documentation:")} http://localhost:${Config.app.port}/apidoc`);
+ if (Config.app.nodeEnv !== "test") {
+ console.log(`${bold("๐บ Werewolves Assistant API")} server started on port ${bold.blue(Config.app.port)} and running on database ${bold.green(Config.db.name)}.`);
+ console.log(`${bold("๐ API Documentation:")} http://localhost:${Config.app.port}/apidoc`);
+ }
app.emit("ready");
- app.prototype.isReady = true;
});
module.exports = app;
\ No newline at end of file
diff --git a/config/apidoc/apidoc.json b/config/apidoc/apidoc.json
index f1b480c..46b15a2 100755
--- a/config/apidoc/apidoc.json
+++ b/config/apidoc/apidoc.json
@@ -1,6 +1,6 @@
{
"name": "\uD83D\uDC3A Werewolves Assistant API",
- "version": "0.10.0",
+ "version": "0.11.0",
"description": "Werewolves Assistant API provides over HTTP requests a way of manage The Werewolves of Millers Hollow games in order to help the game master in his task.",
"header": {
"title": "Classes",
diff --git a/config/apidoc/footer.md b/config/apidoc/footer.md
index 4d45c93..605d710 100644
--- a/config/apidoc/footer.md
+++ b/config/apidoc/footer.md
@@ -35,62 +35,66 @@ Among all players, groups are defined depending on players properties. Some grou
Each player in a game has a role. It defines the original player's side and powers.
-| Role | Card | [Side](#player-sides) | Limits | Description |
-|:-----------------------------------------------:|:-------------------------------------------------------------------------------------------------------------:|:------------------------:|:------------------------------------------------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| ๐บ
werewolf | | werewolves | **Max in game**: 39 | Each night, his group eats a villager chosen by the majority. |
-| ๐บ
big-bad-wolf | | werewolves | **Max in game**: 1 | Each night until no player in the `werewolves` side has died, he eats another villager all by himself after the `werewolves` turn. |
-| ๐บ
vile-father-of-wolves | | werewolves | **Max in game**: 1 | Once in the game, he infects the victim `eaten` by the werewolves and therefore, the infected villager immediately joins the `werewolves`. The victim keeps his original villager powers but must win with the other `werewolves`. |
-| ๐บ
white-werewolf | | werewolves | **Max in game**: 1 | Every other night, starting the first night, he wakes up and can eat another player in the `werewolves` side if he wants to. He is the last werewolf, we doesn't wake up anymore. He is the last survivor, he is the only winner of the game. |
-| ๐งโ๐พ
villager | | villagers | **Max in game**: 39 | Has no powers, can only count on his speech skills. |
-| ๐งโ๐พ๐งโ๐พ
villager-villager | | villagers | **Max in game**: 1 | Like the normal villager, has no power but on the two faces of his role card, there is the illustration of a simple villager. So, everybody knows that it's a simple villager. |
-| ๐ฎ
seer | | villagers | **Max in game**: 1 | Each night, she sees the role of the player she wants. |
-| ๐น
cupid | | villagers | **Max in game**: 1 | The first night, he chooses two players that fall instantly in love (he can choose himself). Next, the lovers wake up to meet each other and must win together. |
-| ๐ช
๏ธโwitch | | villagers | **Max in game**: 1 | She has one life potion which prevents from being eaten by werewolves and a death potion which instantly kills. She can only use each one once in the game. |
-| ๐ซ
hunter | | villagers | **Max in game**: 1 | If he dies, he shoots a victim to take his revenge. He can't kill himself. |
-| ๐ง
little-girl | | villagers | **Max in game**: 1 | She can slightly open her eyes during werewolves turn to spot some of them. Even if the guard protects her, she will die by the werewolves if she is chosen by them. |
-| ๐ก๏ธ
guard | | villagers | **Max in game**: 1 | Each night, he protects the player he wants (including himself). He can't protect the same player twice in a row. |
-| ๐ด๐ผ
ancient | | villagers | **Max in game**: 1 | If he dies from the `werewolves`, he has another life. But if he dies from the `death-potion`, the `vote` or the `hunter`, he dies and all who started the game in the `villagers` side will loose their powers. |
-| ๐
scapegoat | | villagers | **Max in game**: 1 | If there is a tie in votes, even if the `sheriff` is in the game or he is not in the tie, he will be the vote target. If so, he will choose who won't vote during the next day. |
-| ๐คช
idiot | | villagers | **Max in game**: 1 | If he is nominated by the `vote`, he doesn't die but his role is revealed and he can't no more vote. If he dies and was the `sheriff`, he won't delegate the role and there won't be no more `sheriff` for the rest of the game. |
-| ๐ญ
two-sisters | | villagers | **Min in game if chosen**: 2
**Max in game**: 2 | The first night, they meet each other and, therefore, know that they can trust themselves. Depending on game options, they wake up every X night(s). (Default is `2`). |
-| ๐จโ๐จโ๐ฆ
three-brothers | | villagers | **Min in game if chosen**: 3
**Max in game**: 3 | The first night, they meet each other and, therefore, know that they can trust themselves. Depending on game options, they wake up every X night(s). (Default is `2`). |
-| โ๏ธ
stuttering-judge | | villagers | **Max in game**: 1 | The first night, he chooses a sign with the game master. After a vote, once in the game, he can do the sign to the game master and this will cause another vote immediately. |
-| ๐
wild-child | | villagers / werewolves | **Max in game**: 1 | The first night, he chooses a model among the other players. If this model dies during the game, the wild child changes his side to `werewolves` and must win with them. |
-| ๐
dog-wolf | | villagers / werewolves | **Max in game**: 1 | The first night, he chooses a side between `villagers` and `werewolves`. Then, he must win with the chosen side. Other players don't know what he chose. |
-| ๐ฆน
thief | | villagers / werewolves | **Max in game**: 1 | If he's in the party, 2 additional role cards must be added. The first night, he can choose between one of the two cards or keep his original role. If the two cards are in the `werewolves` side, he must choose one of them. |
-| ๐ผ
angel | | villagers | **Max in game**: 1 | He must win alone. When he's in the party, the game starts with a `vote` (after `sheriff` election). If he dies from the first `votes` or by the `werewolves` the first night, he wins the game alone. |
-| ๐ฃ
pied-piper | | villagers | **Max in game**: 1 | He must win alone. Each night, he charms two players, except himself. If all alive players are charmed, he wins the game. If he's infected by the `vile-father-of-wolves`, he looses his ability to charm. |
-| ๐ชถ
raven | | villagers | **Max in game**: 1 | Each night, he can mark someone (including himself) if he wants to. The next phase (during the `day`), the marked player will have two votes against himself for the next vote only. |
+| Role | Card | [Side](#player-sides) | Limits | Description |
+|:-----------------------------------------------:|:-------------------------------------------------------------------------------------------------------------:|:------------------------:|:------------------------------------------------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ๐บ
werewolf | | werewolves | **Max in game**: 39 | Each night, his group eats a villager chosen by the majority. |
+| ๐บ
big-bad-wolf | | werewolves | **Max in game**: 1 | Each night until no player in the `werewolves` side has died, he eats another villager all by himself after the `werewolves` turn. |
+| ๐บ
vile-father-of-wolves | | werewolves | **Max in game**: 1 | Once in the game, he infects the victim `eaten` by the werewolves and therefore, the infected villager immediately joins the `werewolves`. The victim keeps his original villager powers but must win with the other `werewolves`. |
+| ๐บ
white-werewolf | | werewolves | **Max in game**: 1 | Every other night, starting the first night, he wakes up and can eat another player in the `werewolves` side if he wants to. He is the last werewolf, we doesn't wake up anymore. He is the last survivor, he is the only winner of the game. |
+| ๐งโ๐พ
villager | | villagers | **Max in game**: 39 | Has no powers, can only count on his speech skills. |
+| ๐งโ๐พ๐งโ๐พ
villager-villager | | villagers | **Max in game**: 1 | Like the normal villager, has no power but on the two faces of his role card, there is the illustration of a simple villager. So, everybody knows that it's a simple villager. |
+| ๐ฎ
seer | | villagers | **Max in game**: 1 | Each night, she sees the role of the player she wants. |
+| ๐น
cupid | | villagers | **Max in game**: 1 | The first night, he chooses two players that fall instantly in love (he can choose himself). Next, the lovers wake up to meet each other and must win together. |
+| ๐ช
๏ธโwitch | | villagers | **Max in game**: 1 | She has one life potion which prevents from being eaten by werewolves and a death potion which instantly kills. She can only use each one once in the game. |
+| ๐ซ
hunter | | villagers | **Max in game**: 1 | If he dies, he shoots a victim to take his revenge. He can't kill himself. |
+| ๐ง
little-girl | | villagers | **Max in game**: 1 | She can slightly open her eyes during werewolves turn to spot some of them. Even if the guard protects her, she will die by the werewolves if she is chosen by them. |
+| ๐ก๏ธ
guard | | villagers | **Max in game**: 1 | Each night, he protects the player he wants (including himself). He can't protect the same player twice in a row. |
+| ๐ด๐ผ
ancient | | villagers | **Max in game**: 1 | If he dies from the `werewolves`, he has another life. But if he dies from the `death-potion`, the `vote` or the `hunter`, he dies and all who started the game in the `villagers` side will loose their powers. |
+| ๐
scapegoat | | villagers | **Max in game**: 1 | If there is a tie in votes, even if the `sheriff` is in the game or he is not in the tie, he will be the vote target. If so, he will choose who won't vote during the next day. |
+| ๐คช
idiot | | villagers | **Max in game**: 1 | If he is nominated by the `vote`, he doesn't die but his role is revealed and he can't no more vote. If he dies and was the `sheriff`, he won't delegate the role and there won't be no more `sheriff` for the rest of the game. |
+| ๐ญ
two-sisters | | villagers | **Min in game if chosen**: 2
**Max in game**: 2 | The first night, they meet each other and, therefore, know that they can trust themselves. Depending on game options, they wake up every X night(s). (Default is `2`). |
+| ๐จโ๐จโ๐ฆ
three-brothers | | villagers | **Min in game if chosen**: 3
**Max in game**: 3 | The first night, they meet each other and, therefore, know that they can trust themselves. Depending on game options, they wake up every X night(s). (Default is `2`). |
+| ๐ฆ
fox | | villagers | **Max in game**: 1 | Every night, he chooses a player. If this player or one of his neighbors is from the `werewolves` side, the game master will make a positive sign to the `fox. If none is a `werewolf`, the `fox` looses his power for the rest of the game. He can skip his turn if he wants to. |
+| ๐ป
bear-tamer | | villagers | **Max in game**: 1 | Every time the day rises, if one of his alive neighbors is from the `werewolves` side, he growls (he has the `growls` attribute). If he is `infected`, he will growl everyday. |
+| โ๏ธ
stuttering-judge | | villagers | **Max in game**: 1 | The first night, he chooses a sign with the game master. After a vote, once in the game, he can do the sign to the game master and this will cause another vote immediately. |
+| ๐ก
rusty-sword-knight | | villagers | **Max in game**: 1 | If he dies from the `eaten` attribute, the first alive player from the `werewolves` side on his left will have the `contaminated` attribute. This contaminated player will die at the end of the day. |
+| ๐ฆน
thief | | villagers / werewolves | **Max in game**: 1 | If he's in the party, 2 additional role cards must be added. The first night, he can choose between one of the two cards or keep his original role. If the two cards are in the `werewolves` side, he must choose one of them. |
+| ๐
wild-child | | villagers / werewolves | **Max in game**: 1 | The first night, he chooses a model among the other players. If this model dies during the game, the wild child changes his side to `werewolves` and must win with them. |
+| ๐
dog-wolf | | villagers / werewolves | **Max in game**: 1 | The first night, he chooses a side between `villagers` and `werewolves`. Then, he must win with the chosen side. Other players don't know what he chose. |
+| ๐ผ
angel | | villagers | **Max in game**: 1 | He must win alone. When he's in the party, the game starts with a `vote` (after `sheriff` election). If he dies from the first `votes` or by the `werewolves` the first night, he wins the game alone. |
+| ๐ฃ
pied-piper | | villagers | **Max in game**: 1 | He must win alone. Each night, he charms two players, except himself. If all alive players are charmed, he wins the game. If he's infected by the `vile-father-of-wolves`, he looses his ability to charm. |
+| ๐ชถ
raven | | villagers | **Max in game**: 1 | Each night, he can mark someone (including himself) if he wants to. The next phase (during the `day`), the marked player will have two votes against himself for the next vote only. |
## ๐ช Player Actions
Actions can be performed by a group, a role or a player which has a specific attribute.
-| Action | [Role](#player-roles) | [Group](#player-groups) | [Attribute](#player-attributes) | When - Use and Limits |
-|:-----------------:|:---------------------------------:|:-----------------------:|:--------------------------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| eat | ๐บ
werewolf | ๐บ
werewolves | - | Each night - Eat a villager chosen by majority. |
-| eat | ๐บ
big-bad-wolf | ๐บ
werewolves | - | Each night until one player of the `werewolves` side has died - Kill a villager in addition to the `werewolves` target. |
-| eat | ๐บ
white-werewolf | ๐บ
werewolves | - | Every other night starting the first night until there is no other werewolf other than him - Kill a werewolf. |
-| look | ๐ฎ
seer | ๐งโ๐พ
villagers | - | Each night - Reveal a role. |
-| charm | ๐น
cupid | ๐งโ๐พ
villagers | - | First night - Charm two people who have to win together. |
-| use-potion | ๐ช
witch | ๐งโ๐พ
villagers | - | Each night - Protect or kill. One use available for each life and death potion. |
-| shoot | ๐ซ
hunter | ๐งโ๐พ
villagers | - | When hunter dies - Kill someone chosen by hunter, can't be himself. |
-| protect | ๐ก๏ธ
guard | ๐งโ๐พ
villagers | - | Each night - Prevents from death for the night. Can't protect the same player twice in a row. |
-| mark | ๐ชถ
raven | ๐งโ๐พ
villagers | - | Each night - Mark someone. The next day, the target will have 2 votes against himself. The mark goes away after the judgement. |
-| meet-each-other | ๐ญ
two-sisters | ๐งโ๐พ
villagers | - | First night and every X night depending on game options. Brief moment in which sisters meet each other and can speak (with gestures). |
-| meet-each-other | ๐จโ๐จโ๐ฆ
three-brothers | ๐งโ๐พ
villagers | - | First night and every X night depending on game options. Brief moment in which brothers meet each other and can speak (with gestures). |
-| choose-model | ๐
wild-child | ๐งโ๐พ
villagers | - | First night - The wild child chooses his model among the players. If the model dies, wild child changes side to `werewolves`. He can't choose himself. |
-| choose-side | ๐
dog-wolf | ๐งโ๐พ
villagers | - | First night - The dog-wolf chooses his side between `villagers` and `werewolves` and must win with the chosen side. |
-| ban-voting | ๐
scapegoat | ๐งโ๐พ
villagers | - | When scapegoat dies from a tie in votes - He chooses who won't be able to vote during the next day. If no one can vote, there won't be votes during this day. |
-| charm | ๐ฃ
pied-piper | ๐งโ๐พ
villagers | - | Each night - He charms two players which will have the `charmed` attribute for the rest of the game. Charmed players meet each other right after pied piper turn.|
-| choose-sign | โ๏ธ
stuttering-judge | ๐งโ๐พ
villagers | - | First night - He chooses a sign to do with the game master to cause a second vote. |
-| choose-card | ๐ฆน๏ธ
thief | ๐งโ๐พ
villagers | - | First night - He can choose a card from the additional cards. |
-| elect-sheriff | - | ๐ช
all | - | During the first phase (`night`) - Anyone can be elected as a sheriff. |
-| vote | - | ๐ช
all | - | Each day - All alive players vote for someone to kill. |
-| delegate | - | - | ๐
sheriff | When sheriff dies - The dying sheriff chooses the next one in among the living. |
-| settle-votes | - | - | ๐
sheriff | When there is a tie in the votes during the `day` - Choose which one will be executed. |
-| meet-each-other | - | - | ๐
in-love | Right after Cupid chose his targets, lovers wake up and meet each other. |
-| meet-each-other | - | - | ๐บ๏ธ
charmed | Right after pied piper chose his targets, all charmed players (new and old) wake up and meet each other. |
+| Action | [Role](#player-roles) | [Group](#player-groups) | [Attribute](#player-attributes) | When - Use and Limits |
+|:-----------------:|:---------------------------------:|:-----------------------:|:--------------------------------:|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| eat | ๐บ
werewolf | ๐บ
werewolves | - | Each night - Eat a villager chosen by majority. |
+| eat | ๐บ
big-bad-wolf | ๐บ
werewolves | - | Each night until one player of the `werewolves` side has died - Kill a villager in addition to the `werewolves` target. |
+| eat | ๐บ
white-werewolf | ๐บ
werewolves | - | Every other night starting the first night until there is no other werewolf other than him - Kill a werewolf. |
+| look | ๐ฎ
seer | ๐งโ๐พ
villagers | - | Each night - Reveal a role. |
+| charm | ๐น
cupid | ๐งโ๐พ
villagers | - | First night - Charm two people who have to win together. |
+| use-potion | ๐ช
witch | ๐งโ๐พ
villagers | - | Each night - Protect or kill. One use available for each life and death potion. |
+| shoot | ๐ซ
hunter | ๐งโ๐พ
villagers | - | When hunter dies - Kill someone chosen by hunter, can't be himself. |
+| protect | ๐ก๏ธ
guard | ๐งโ๐พ
villagers | - | Each night - Prevents from death for the night. Can't protect the same player twice in a row. |
+| mark | ๐ชถ
raven | ๐งโ๐พ
villagers | - | Each night - Mark someone. The next day, the target will have 2 votes against himself. The mark goes away after the judgement. |
+| meet-each-other | ๐ญ
two-sisters | ๐งโ๐พ
villagers | - | First night and every X night depending on game options. Brief moment in which sisters meet each other and can speak (with gestures). |
+| meet-each-other | ๐จโ๐จโ๐ฆ
three-brothers | ๐งโ๐พ
villagers | - | First night and every X night depending on game options. Brief moment in which brothers meet each other and can speak (with gestures). |
+| sniff | ๐ฆ
fox | ๐งโ๐พ
villagers | - | Each night - The fox chooses a group of 3 people by pointing the player on the center. Game master makes a positive sign if one of the group is from the `werewolves` side or looses his power otherwise. |
+| choose-model | ๐
wild-child | ๐งโ๐พ
villagers | - | First night - The wild child chooses his model among the players. If the model dies, wild child changes side to `werewolves`. He can't choose himself. |
+| choose-side | ๐
dog-wolf | ๐งโ๐พ
villagers | - | First night - The dog-wolf chooses his side between `villagers` and `werewolves` and must win with the chosen side. |
+| ban-voting | ๐
scapegoat | ๐งโ๐พ
villagers | - | When scapegoat dies from a tie in votes - He chooses who won't be able to vote during the next day. If no one can vote, there won't be votes during this day. |
+| charm | ๐ฃ
pied-piper | ๐งโ๐พ
villagers | - | Each night - He charms two players which will have the `charmed` attribute for the rest of the game. Charmed players meet each other right after pied piper turn. |
+| choose-sign | โ๏ธ
stuttering-judge | ๐งโ๐พ
villagers | - | First night - He chooses a sign to do with the game master to cause a second vote. |
+| choose-card | ๐ฆน๏ธ
thief | ๐งโ๐พ
villagers | - | First night - He can choose a card from the additional cards. |
+| elect-sheriff | - | ๐ช
all | - | During the first phase (`night`) - Anyone can be elected as a sheriff. |
+| vote | - | ๐ช
all | - | Each day - All alive players vote for someone to kill. |
+| delegate | - | - | ๐
sheriff | When sheriff dies - The dying sheriff chooses the next one in among the living. |
+| settle-votes | - | - | ๐
sheriff | When there is a tie in the votes during the `day` - Choose which one will be executed. |
+| meet-each-other | - | - | ๐
in-love | Right after Cupid chose his targets, lovers wake up and meet each other. |
+| meet-each-other | - | - | ๐บ๏ธ
charmed | Right after pied piper chose his targets, all charmed players (new and old) wake up and meet each other. |
## ๐๏ธ Player Attributes
@@ -107,25 +111,28 @@ Attributes are consequences of actions and hold by players. Each attribute has s
| ๐ชถ
raven-marked | The raven marked the player during the night. During the next phase (`day`), this player will have two votes against himself. | 2 phases
(_1 turn_) |
| ๐
in-love | Shot by the Cupid arrow, players with this attribute must win together the game. If one dies, the other one dies too. | Last forever
(`remainingPhases` _not set_) |
| ๐
worshiped | The wild child chose the player during the first night. If the player dies, the wild child changes his side to `werewolves`. | Last forever
(`remainingPhases` _not set_) |
-| ๐คทโ
powerless | The ancient died from the `hunter`, the `witch` or from the `vote`, all who started the game in the `villagers` side will have this attribute and therefore, won't be able to use their powers anymore. | Last forever
(`remainingPhases` _not set_) |
+| ๐คทโ
powerless | This player can't use his power anymore. | Last forever
(`remainingPhases` _not set_) |
| ๐ซ๐ณ๏ธโ
cant-vote | The player is not able to vote while he has this attribute. If all alive players have this attribute, there is no vote. | From the `scapegoat`: 2 phases
(_1 turn_)
From the `idiot`: Last forever
(`remainingPhases` _not set_) |
| ๐บ๏ธโ
charmed | The pied piper charmed this player during the night. If all alive players have this attribute, the pied piper wis the game. | Last forever
(`remainingPhases` _not set_) |
+| ๐ปโ
growls | The bear tamer has one of his alive neighbors from the `werewolves` side or is himself `infected`. | 1 phase |
+| ๐ฆ โ
contaminated | The player will die at the end of the day because he's from the `werewolves` side and the nearest left neighbor of the `rusty-sword-knight`. | 1 phase |
## โ ๏ธ Player Deaths
During the game, players can die from multiple causes.
-| Source | Cause | Possible target(s) | Description |
-|:----------------------:|:------------:|:------------------------------------------:|--------------------------------------------------------------------------------------------------------------------------|
-| ๐ช
๏ธโwitch | use-potion | All alive players | This player died from drinking the death potion, there is no antidote. |
-| ๐บ
werewolves | eat | All alive players in the `villagers` side | This player has been eaten by the `werewolves` and was not protected by the `guard` and didn't drink the life potion. |
-| ๐บ
big-bad-wolf | eat | All alive players in the `villagers` side | This player has been eaten by the `big-bad-wolf` and was not protected by the `guard` and didn't drink the life potion. |
-| ๐บ
white-werewolf | eat | All alive players in the `werewolves` side | This player has been eaten by the `white-werewolf` and there is no protection about it. |
-| ๐ซ
hunter | shoot | All alive players | This player has been shoot by the hunter who just died. |
-| ๐๏ธ
sheriff | settle-votes | Players involved in the tie in votes | This player has been chosen by the sheriff to die after being in the tie in votes during the previous play. |
-| ๐ช
all | vote | All alive players | This player has been chosen by the village to be hanged after votes. |
-| ๐น
cupid | charm | Players with `in-love` attribute | The other `in-love` player died, and then his beloved one died from love. |
-| ๐ช
all | reconsider | Player with `idiot` role | The player with the `idiot` role was already revealed and the `ancient` died. |
+| Source | Cause | Possible target(s) | Description |
+|:--------------------------:|:------------:|:------------------------------------------:|--------------------------------------------------------------------------------------------------------------------------|
+| ๐ช
๏ธโwitch | use-potion | All alive players | This player died from drinking the death potion, there is no antidote. |
+| ๐บ
werewolves | eat | All alive players in the `villagers` side | This player has been eaten by the `werewolves` and was not protected by the `guard` and didn't drink the life potion. |
+| ๐บ
big-bad-wolf | eat | All alive players in the `villagers` side | This player has been eaten by the `big-bad-wolf` and was not protected by the `guard` and didn't drink the life potion. |
+| ๐บ
white-werewolf | eat | All alive players in the `werewolves` side | This player has been eaten by the `white-werewolf` and there is no protection about it. |
+| ๐ซ
hunter | shoot | All alive players | This player has been shoot by the hunter who just died. |
+| ๐๏ธ
sheriff | settle-votes | Players involved in the tie in votes | This player has been chosen by the sheriff to die after being in the tie in votes during the previous play. |
+| ๐ช
all | vote | All alive players | This player has been chosen by the village to be hanged after votes. |
+| ๐น
cupid | charm | Players with `in-love` attribute | The other `in-love` player died, and then his beloved one died from love. |
+| ๐ช
all | reconsider | Player with `idiot` role | The player with the `idiot` role was already revealed and the `ancient` died. |
+| ๐ก
rusty-sword-knight | disease | All alive players in the `werewolves` side | This werewolf was the nearest left player of the `rusty-sword-knight` after eating him. |
## โ ๏ธ Errors
@@ -188,7 +195,7 @@ Description for each case below :
| 51 | CANT_EAT_HIMSELF | 400 | White werewolf can't eat himself. |
| 52 | STUTTERING_JUDGE_ABSENT | 400 | Second vote can't be requested if stuttering judge is absent from the game. |
| 53 | STUTTERING_JUDGE_POWERLESS | 400 | Stuttering judge is powerless and so can't request another vote. |
-| 54 | ONLY_ONE_SECOND_VOTE_REQUEST | 400 | Second vote request has been already made. |
+| 54 | VOTE_REQUESTS_EXCEEDED | 400 | Stuttering judge doesn't have any vote request left. |
| 55 | BAD_PLAY_ACTION_FOR_SIDE_CHOICE | 400 | `side` can be set only if play's action is `choose-side`. |
| 56 | BAD_PLAY_ACTION_FOR_JUDGE_REQUEST | 400 | `doesJudgeRequestAnotherVote` can be set only if play's action is `vote`. |
| 57 | BAD_PLAY_ACTION_FOR_INFECTION | 400 | `isInfected` can be set on target only if play's action is `eat`. |
@@ -196,7 +203,17 @@ Description for each case below :
| 59 | STUTTERING_JUDGE_DIDNT_CHOOSE_SIGN_YET | 400 | Stuttering judge didn't choose his sign yet and so can't request another vote. |
| 60 | ADDITIONAL_CARDS_NOT_ALLOWED | 400 | `additionalCards` is not allowed when there is no `thief` in game. |
| 61 | FORBIDDEN_ADDITIONAL_CARD_ROLE_FOR_THIEF | 400 | Role is not allowed in additional cards for thief. |
-| 62 | NEED_ADDITIONAL_CARDS_FOR_THIEF | 400 | When `thief` is in the game, 2 additional cards must be added for him. |
+| 62 | NEED_ADDITIONAL_CARDS_FOR_THIEF | 400 | When `thief` is in the game, 2 additional cards must be added for him (depending on game's options). |
| 63 | BAD_PLAY_ACTION_FOR_CHOSEN_CARD | 400 | `card` can be set only if action is `choose-card`. |
| 64 | CHOSEN_CARD_NOT_FOUND | 404 | The chosen card is not found in additional cards. |
-| 65 | THIEF_MUST_STEAL | 400 | As all additional cards for thief are on the werewolves side, he must choose one of them. |
\ No newline at end of file
+| 65 | THIEF_MUST_STEAL | 400 | As all additional cards for thief are on the werewolves side, he must choose one of them. |
+| 66 | ALL_PLAYERS_POSITION_NOT_SET | 400 | Some players has a position and other not. You must define all position or none of them. |
+| 67 | PLAYERS_POSITION_NOT_UNIQUE | 400 | Players don't all have unique position. |
+| 68 | PLAYER_POSITION_TOO_HIGH | 400 | One player's position exceeds the maximum. |
+| 69 | THIEF_ADDITIONAL_CARDS_COUNT_NOT_RESPECTED | 400 | Exactly 2 additional cards are needed for thief (depending on game's options). |
+| 70 | BAD_FACEBOOK_ACCESS_TOKEN | 400 | Access token doesn't allow to get user info. |
+| 71 | NEED_FACEBOOK_EMAIL_PERMISSION | 400 | You need to share your email to login with Facebook. |
+| 72 | EMAIL_EXISTS_WITH_LOCAL_REGISTRATION | 400 | The email provided already exists with local registration. |
+| 73 | EMAIL_EXISTS_WITH_FACEBOOK_REGISTRATION | 400 | The email provided already exists with facebook registration. |
+| 74 | EMAIL_EXISTS_WITH_GOOGLE_REGISTRATION | 400 | The email provided already exists with google registration. |
+| 75 | BAD_GOOGLE_ID_TOKEN | 400 | Id token doesn't allow to get user info. |
\ No newline at end of file
diff --git a/config/apidoc/header.md b/config/apidoc/header.md
index f6e200e..21669ba 100644
--- a/config/apidoc/header.md
+++ b/config/apidoc/header.md
@@ -19,12 +19,14 @@
In order to log in and create games, a user must be created (aka the future game master).
-| Field | Type | Description |
-|----------------------|:--------:|---------------------------------------------------------------------|
-| _id | ObjectId | User's ID. |
-| email | String | User's email. |
-| createdAt | Date | When the user created his account. |
-| updatedAt | Date | When the user updated his account. |
+| Field | Type | Description |
+|----------------------|:--------:|-----------------------------------------------------------------------------------------|
+| _id | ObjectId | User's ID. |
+| email | String | User's email. |
+| registration | Object | User's registration data. |
+| โฎ method | String | How the user registered himself. (_Possibilities: `local`, `facebook` or `google`_) |
+| createdAt | Date | When the user created his account. |
+| updatedAt | Date | When the user updated his account. |
## ๐ฒ Game
@@ -50,47 +52,79 @@ At the end of the game, winner(s) are set in the `won` property.
When game's status is `done` or `canceled`, it can be reviewed by the game master.
-| Field | Type | Description |
-|-------------------------------------------------------------------------------|:-------------------------------------------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| _id | ObjectId | Game's ID. |
-| gameMaster | User | User who created the game and managing it. (_See: [Classes - User](#user-class)_) |
-| players | [Player[]](#player-class) | Players of the game. |
-| turn | Number | Starting at `1`, a turn starts with the first phase (the `night`) and ends with the second phase (the `day`). |
-| phase | String | Each turn has two phases, `day` or `night`. Starting at `night`. |
-| tick | Number | Starting at `1`, tick increments each time a play is made. |
-| waiting | Object[] | Queue of upcoming actions and sources. |
-| โฎ for | String | Can be either a group, a role or the sheriff. (_See: [Codes - Player Groups](#player-groups) or [Codes - Player Roles](#player-roles) or `sheriff`_) |
-| โฎ to | String | What action needs to be performed by `waiting.for`. (_See: [Codes - Player Actions](#player-actions)_) |
-| ** โฎ cause*** | String | The cause of action. (_Possibilities: `stuttering-judge-request`_) |
-| status | String | Game's current status. (_See: [Codes - Game Statuses](#game-statuses)_) |
-| **additionalCards*** | [AdditionalCard[]](#game-additional-card-class) | Game's additional cards. Set if `thief` is in the game. |
-| options | Object | Game's options. |
-| โฎ roles | Object | Game roles options. |
-| โฎ sheriff | Object | Game sheriff role's options. |
-| โฎ isEnabled | Boolean | If set to `true`, `sheriff` will be elected the first tick and the responsibility will be delegated when he dies. Otherwise, there will be no sheriff in the game and tie in votes will result in another vote between the tied players. In case of another equality, there will be no vote. |
-| โฎ hasDoubledVote | Boolean | If set to `true`, `sheriff` vote during the village's vote is doubled, otherwise, it's a regular vote. Default is `true`. |
-| โฎ seer | Object | Game seer role's options. |
-| โฎ isTalkative | Boolean | If set to `true`, the game master must say out loud what the seer saw during her night, otherwise, he must mime the seen role to the seer. Default is `true`. |
-| โฎ littleGirl | Object | Game little girl role's options. |
-| โฎ isProtectedByGuard | Boolean | If set to `false`, the little girl won't be protected by the guard from the werewolves attacks. Default is `false`. |
-| โฎ idiot | Object | Game idiot role's options. |
-| โฎ doesDieOnAncientDeath | Boolean | If set to `true`, the idiot will die if he is revealed and the ancient is dead. Default is `true`. |
-| โฎ twoSisters | Object | Game two sisters role's options. |
-| โฎ wakingUpInterval | Number | Since first `night`, interval of nights when the Two Sisters are waking up. Default is `2`, meaning they wake up every other night. If set to `0`, they are waking up the first night only. |
-| โฎ threeBrothers | Object | Game three brothers role's options. |
-| โฎ wakingUpInterval | Number | Since first `night`, interval of nights when the Three Brothers are waking up. Default is `2`, meaning they wake up every other night. If set to `0`, they are waking up the first night only. |
-| โฎ raven | Object | Game raven's role options. |
-| โฎ markPenalty | Number | Penalty of votes against the player targeted by the raven mark for the next village's vote. Default is `2`, meaning that the raven marked player will have two votes against himself. |
-| history | [GameHistory[]](#game-history-class) | Game's history. Limited by default to `3` entries. (_See: [Classes - Game History Entry](#game-history-class)_) |
-| **won*** | Object | Winner(s) of the game when status is `done`. |
-| โฎ by | String | Can be either a group or a role. (_Possibilities: `werewolves`, `villagers`, `lovers`, `pied-piper`, `white-werewolf` or null if nobody won_) |
-| ** โฎ players*** | [Player[]](#player-class) | List of player(s) who won. (_See: [Classes - Player](#player-class)_) |
-| **review*** | Object | Game master can attach a game review only if its status is set to `canceled` or `done`. |
-| โฎ rating | Number | Review's rating, from 0 to 5. |
-| ** โฎ comment*** | String | Review's comment, from 1 to 500 characters long. |
-| ** โฎ dysfunctionFound*** | Boolean | If a bug or a dysfunction was found during the game. |
-| createdAt | Date | When the user created his account. |
-| updatedAt | Date | When the user updated his account. |
+| Field | Type | Description |
+|-------------------------------------------------------------------------------|:-------------------------------------------------:|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| _id | ObjectId | Game's ID. |
+| gameMaster | User | User who created the game and managing it. (_See: [Classes - User](#user-class)_) |
+| players | [Player[]](#player-class) | Players of the game. |
+| turn | Number | Starting at `1`, a turn starts with the first phase (the `night`) and ends with the second phase (the `day`). |
+| phase | String | Each turn has two phases, `day` or `night`. Starting at `night`. |
+| tick | Number | Starting at `1`, tick increments each time a play is made. |
+| waiting | Object[] | Queue of upcoming actions and sources. |
+| โฎ for | String | Can be either a group, a role or the sheriff. (_See: [Codes - Player Groups](#player-groups) or [Codes - Player Roles](#player-roles) or `sheriff`_) |
+| โฎ to | String | What action needs to be performed by `waiting.for`. (_See: [Codes - Player Actions](#player-actions)_) |
+| ** โฎ cause*** | String | The cause of action. (_Possibilities: `stuttering-judge-request`_) |
+| status | String | Game's current status. (_See: [Codes - Game Statuses](#game-statuses)_) |
+| **additionalCards*** | [AdditionalCard[]](#game-additional-card-class) | Game's additional cards. Set if `thief` is in the game. |
+| options | Object | Game's options. |
+| โฎ repartition | Object | Game repartition's options. |
+| โฎ isHidden | Boolean | If set to `true`, game's repartition will be hidden to all players. Default is `false`. |
+| โฎ roles | Object | Game roles options. |
+| โฎ areRevealedOnDeath | Boolean | If set to `true`, player's role is revealed when he's dead. Default is `true`. |
+| โฎ sheriff | Object | Game sheriff role's options. |
+| โฎ isEnabled | Boolean | If set to `true`, `sheriff` will be elected the first tick and the responsibility will be delegated when he dies. Otherwise, there will be no sheriff in the game and tie in votes will result in another vote between the tied players. In case of another equality, there will be no vote. Default is `true`. |
+| โฎ electedAt | Object | When the sheriff is elected during the game. |
+| โฎ turn | Number | Game's turn when the sheriff is elected. Default is `1`. |
+| โฎ phase | String | Game's phase when the sheriff is elected. Default is `night`. |
+| โฎ hasDoubledVote | Boolean | If set to `true`, `sheriff` vote during the village's vote is doubled, otherwise, it's a regular vote. Default is `true`. |
+| โฎ bigBadWolf | Object | Game big bad wolf role's options. |
+| โฎ isPowerlessIfWerewolfDies | Boolean | If set to `true`, `big-bad-wolf` won't wake up anymore during the night if at least one player from the `werewolves` side died. Default is `true`. |
+| โฎ whiteWerewolf | Object | Game white werewolf role's options. |
+| โฎ wakingUpInterval | Number | Since first `night`, interval of nights when the `white-werewolf` is waking up. Default is `2`, meaning he wakes up every other night. |
+| โฎ seer | Object | Game seer role's options. |
+| โฎ isTalkative | Boolean | If set to `true`, the game master must say out loud what the seer saw during her night, otherwise, he must mime the seen role to the seer. Default is `true`. |
+| โฎ canSeeRoles | Boolean | If set to `true`, the seer can the exact `role` of the target, otherwise, she only sees the `side`. Default is `true`. |
+| โฎ littleGirl | Object | Game little girl role's options. |
+| โฎ isProtectedByGuard | Boolean | If set to `false`, the little girl won't be protected by the guard from the werewolves attacks. Default is `false`. |
+| โฎ guard | Object | Game guard role's options. |
+| โฎ canProtectTwice | Boolean | If set to `true`, the guard can protect twice in a row the same target. Default is `false`. |
+| โฎ ancient | Object | Game ancient role's options. |
+| โฎ livesCountAgainstWerewolves | Number | Number of lives ancient has against `werewolves`. Default is `2`. |
+| โฎ doesTakeHisRevenge | Boolean | If set to `true`, the `ancient` will make all players from the `villagers` side `powerless` if he dies from them. Default is `true`. |
+| โฎ idiot | Object | Game idiot role's options. |
+| โฎ doesDieOnAncientDeath | Boolean | If set to `true`, the idiot will die if he is revealed and the ancient is dead. Default is `true`. |
+| โฎ twoSisters | Object | Game two sisters role's options. |
+| โฎ wakingUpInterval | Number | Since first `night`, interval of nights when the Two Sisters are waking up. Default is `2`, meaning they wake up every other night. If set to `0`, they are waking up the first night only. |
+| โฎ threeBrothers | Object | Game three brothers role's options. |
+| โฎ wakingUpInterval | Number | Since first `night`, interval of nights when the Three Brothers are waking up. Default is `2`, meaning they wake up every other night. If set to `0`, they are waking up the first night only. |
+| โฎ fox | Object | Game fox's role options. |
+| โฎ isPowerlessIfMissesWerewolf | Boolean | If set to `true`, the fox will loose his power if he doesn't find a player from the `werewolves` side during his turn if he doesn't skip. Default is `true`. |
+| โฎ bearTamer | Object | Game bear tamer's role options. |
+| โฎ doesGrowlIfInfected | Boolean | If set to `true`, the bear tamer will have the `growls` attribute until he dies if he is `infected`. Default is `true`. |
+| โฎ stutteringJudge | Object | Game stuttering judge's role options. |
+| โฎ voteRequestsCount | Number | Number of vote requests that the `stuttering-judge` can make during the game. Default is `1`. |
+| โฎ wildChild | Object | Game wild child's role options. |
+| โฎ isTransformationRevealed | Boolean | If set to `true`, when `wild-child` joins the `werewolves` side because his model died, the game master will announce his transformation to other players. Default is `false`. |
+| โฎ dogWolf | Object | Game dog wolf's role options. |
+| โฎ isChosenSideRevealed | Boolean | If set to `true`, when `dog-wolf` chooses his side at the beginning of the game, the game master will announce the chosen side to other players. Default is `false`. |
+| โฎ thief | Object | Game thief's role options. |
+| โฎ mustChooseBetweenWerewolves | Boolean | If set to `true`, if all `thief` additional cards are from the `werewolves` side, he can't skip and must choose one. Default is `true`. |
+| โฎ additionalCardsCount | Number | Number of additional cards for the `thief` at the beginning of the game. Default is `2`. |
+| โฎ piedPiper | Object | Game pied piper's role options. |
+| โฎ charmedPeopleCountPerNight | Number | Number of charmed people by the `pied-piper` per night if there are enough targets (or number of not charmed players otherwise). Default is `2`. |
+| โฎ isPowerlessIfInfected | Boolean | If set to `true`, `pied-piper` will be powerless if he is infected by the `vile-father-of-wolves`. Default is `true`. |
+| โฎ raven | Object | Game raven's role options. |
+| โฎ markPenalty | Number | Penalty of votes against the player targeted by the raven mark for the next village's vote. Default is `2`, meaning that the raven marked player will have two votes against himself. |
+| history | [GameHistory[]](#game-history-class) | Game's history. Limited by default to `3` entries. (_See: [Classes - Game History Entry](#game-history-class)_) |
+| **won*** | Object | Winner(s) of the game when status is `done`. |
+| โฎ by | String | Can be either a group or a role. (_Possibilities: `werewolves`, `villagers`, `lovers`, `pied-piper`, `white-werewolf` or null if nobody won_) |
+| ** โฎ players*** | [Player[]](#player-class) | List of player(s) who won. (_See: [Classes - Player](#player-class)_) |
+| **review*** | Object | Game master can attach a game review only if its status is set to `canceled` or `done`. |
+| โฎ rating | Number | Review's rating, from 0 to 5. |
+| ** โฎ comment*** | String | Review's comment, from 1 to 500 characters long. |
+| ** โฎ dysfunctionFound*** | Boolean | If a bug or a dysfunction was found during the game. |
+| createdAt | Date | When the user created his account. |
+| updatedAt | Date | When the user updated his account. |
## ๐บโก๐ง Player
@@ -122,6 +156,7 @@ When a player is killed, `isAlive` is set to `false` and `murdered` object is fi
| ** โฎ activeAt*** | Object | When the attribute will become active and will have consequences on players. Used for attributes with delay. If not set, the attribute is immediately active. |
| โฎ turn | Number | From which game's turn the attribute will become active. |
| ** โฎ phase*** | String | From which game turn's phase (`day` or `night`) the attribute will become active. |
+| position | Number | Unique player's position among all game's players. Increment from `0` to `players.length - 1`. |
| isAlive | Boolean | If the player is currently alive or not. |
| **murdered*** | Object | Set if `isAlive` is `false`. |
| โฎ by | String | Which role or group killed the player. (_Possibilities: [Codes - Player Roles](#player-roles) or [Codes - Player Groups](#player-groups) or `sheriff`_) |
@@ -138,6 +173,7 @@ All available roles of this version can be gathered on the [route GET /roles](#a
| _id | ObjectId | Role's ID. |
| name | String | Role's name. |
| side | String | Role's original side. |
+| type | String | Role's type. (_Possibilities: `villager`, `werewolf`, `ambiguous`, `lonely`_) |
| **minInGame*** | Number | If the role is chosen by at least one player, then minimum X players must choose it to start the game. |
| maxInGame | Number | Maximum possible of this role in a game. |
| **recommendedMinPlayers*** | Number | It is recommended to have at least X players in game for choosing this role. |
diff --git a/config/index.js b/config/index.js
index 2e5c54d..6fbde93 100644
--- a/config/index.js
+++ b/config/index.js
@@ -22,6 +22,8 @@ const Config = {
projectID: process.env.SENTRY_PROJECT_ID,
key: process.env.SENTRY_KEY,
},
+ google: { client: { ID: process.env.GOOGLE_CLIENT_ID } },
+ facebook: { app: { ID: process.env.FACEBOOK_APP_ID } },
};
if (Config.app.nodeEnv === "test") {
diff --git a/package-lock.json b/package-lock.json
index c2052db..01ac145 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,4896 +1,8 @@
{
"name": "werewolwes-assistant-api",
- "version": "0.10.0",
- "lockfileVersion": 2,
+ "version": "0.11.0",
+ "lockfileVersion": 1,
"requires": true,
- "packages": {
- "": {
- "name": "werewolwes-assistant-api",
- "version": "0.10.0",
- "license": "ISC",
- "dependencies": {
- "@sentry/node": "^6.0.3",
- "apidoc": "^0.26.0",
- "bcrypt": "^5.0.0",
- "body-parser": "^1.19.0",
- "colors": "^1.4.0",
- "cors": "^2.8.5",
- "deepmerge": "^4.2.2",
- "dotenv": "^8.2.0",
- "express": "^4.17.1",
- "express-rate-limit": "^5.2.3",
- "express-validator": "^6.9.2",
- "jsonwebtoken": "^8.5.1",
- "migrate-mongo": "^8.1.4",
- "mongo-dot-notation": "^2.0.0",
- "mongoose": "^5.11.14",
- "passport": "^0.4.1",
- "passport-http": "^0.3.0",
- "passport-jwt": "^4.0.0",
- "passport-local": "^1.0.0",
- "qs": "^6.9.6",
- "requirejs": "^2.3.6",
- "validator": "^13.5.2",
- "xss": "^1.0.8"
- },
- "devDependencies": {
- "chai": "^4.2.0",
- "chai-http": "^4.3.0",
- "eslint": "^7.19.0",
- "mocha": "^8.2.1",
- "nodemon": "^2.0.7"
- }
- },
- "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,
- "dependencies": {
- "@babel/highlight": "^7.10.4"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
- "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
- "dev": true
- },
- "node_modules/@babel/highlight": {
- "version": "7.13.8",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.8.tgz",
- "integrity": "sha512-4vrIhfJyfNf+lCtXC2ck1rKSzDwciqF7IWFhXXrSOUC2O5DrVp+w4c6ed4AllTxhTkUP5x2tYj41VaxdVMMRDw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.12.11",
- "chalk": "^2.0.0",
- "js-tokens": "^4.0.0"
- }
- },
- "node_modules/@babel/highlight/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/@babel/highlight/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/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/@babel/highlight/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/@babel/highlight/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true,
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/@babel/highlight/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/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==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@dabh/diagnostics": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz",
- "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==",
- "dependencies": {
- "colorspace": "1.1.x",
- "enabled": "2.0.x",
- "kuler": "^2.0.0"
- }
- },
- "node_modules/@eslint/eslintrc": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
- "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==",
- "dev": true,
- "dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.1.1",
- "espree": "^7.3.0",
- "globals": "^12.1.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"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dev": true,
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/@eslint/eslintrc/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==",
- "dev": true
- },
- "node_modules/@mapbox/node-pre-gyp": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.0.tgz",
- "integrity": "sha512-mEaiD1CURETR/dBIiJAwz0M0Q0mH3gCW4pPMaIlNt97mdzYUVeqGcTJSamgJpS6Tg4tBHDrOJpjdh5fJTLnyNQ==",
- "dependencies": {
- "detect-libc": "^1.0.3",
- "http-proxy-agent": "^4.0.1",
- "mkdirp": "^1.0.4",
- "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"
- }
- },
- "node_modules/@sentry/core": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.2.1.tgz",
- "integrity": "sha512-jPqQEtafxxDtLONhCbTHh/Uq8mZRhsfbwJTSVYfPVEe/ELfFZLQK7tP6rOh7zEWKbTkE0mE6XcaoH3ZRAhgrqg==",
- "dependencies": {
- "@sentry/hub": "6.2.1",
- "@sentry/minimal": "6.2.1",
- "@sentry/types": "6.2.1",
- "@sentry/utils": "6.2.1",
- "tslib": "^1.9.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@sentry/hub": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.1.tgz",
- "integrity": "sha512-pG7wCQeRpzeP6t0bT4T0X029R19dbDS3/qswF8BL6bg0AI3afjfjBAZm/fqn1Uwe/uBoMHVVdbxgJDZeQ5d4rQ==",
- "dependencies": {
- "@sentry/types": "6.2.1",
- "@sentry/utils": "6.2.1",
- "tslib": "^1.9.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@sentry/minimal": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.1.tgz",
- "integrity": "sha512-wuSXB4Ayxv9rBEQ4pm7fnG4UU2ZPtPnnChoEfd4/mw1UthXSvmPFEn6O4pdo2G8fTkl8eqm6wT/Q7uIXMEmw+A==",
- "dependencies": {
- "@sentry/hub": "6.2.1",
- "@sentry/types": "6.2.1",
- "tslib": "^1.9.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@sentry/node": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.2.1.tgz",
- "integrity": "sha512-JlixtJHS6xMzh2G4Pz7oMM8Nd40mGUALQYtuGMwW2QE3IduOaaGsn1+eVpN6PwZetMnvRIn6VVFOc2UmFIzWpA==",
- "dependencies": {
- "@sentry/core": "6.2.1",
- "@sentry/hub": "6.2.1",
- "@sentry/tracing": "6.2.1",
- "@sentry/types": "6.2.1",
- "@sentry/utils": "6.2.1",
- "cookie": "^0.4.1",
- "https-proxy-agent": "^5.0.0",
- "lru_map": "^0.3.3",
- "tslib": "^1.9.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@sentry/tracing": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.2.1.tgz",
- "integrity": "sha512-bvStY1SnL08wkSeVK3j9K5rivQQJdKFCPR2VYRFOCaUoleZ6ChPUnBvxQ/E2LXc0hk/y/wo1q4r5B0dfCCY+bQ==",
- "dependencies": {
- "@sentry/hub": "6.2.1",
- "@sentry/minimal": "6.2.1",
- "@sentry/types": "6.2.1",
- "@sentry/utils": "6.2.1",
- "tslib": "^1.9.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@sentry/types": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.1.tgz",
- "integrity": "sha512-h0OV1QT+fv5ojfK5/+iEXClu33HirmvbjcQC2jf05IHj9yXIOWy6EB10S8nBjuLiiFqQiAQYj3FN9Ip4eN8NJA==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@sentry/utils": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.1.tgz",
- "integrity": "sha512-6kQgM/yBPdXu+3qbJnI6HBcWztN9QfiMkH++ZiKk4ERhg9d2LYWlze478uTU5Fyo/JQYcp+McpjtjpR9QIrr0g==",
- "dependencies": {
- "@sentry/types": "6.2.1",
- "tslib": "^1.9.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@sindresorhus/is": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
- "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@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==",
- "dependencies": {
- "defer-to-connect": "^1.0.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@tootallnate/once": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
- "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/@types/bson": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz",
- "integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/chai": {
- "version": "4.2.15",
- "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.15.tgz",
- "integrity": "sha512-rYff6FI+ZTKAPkJUoyz7Udq3GaoDZnxYDEvdEdFZASiA7PoErltHezDishqQiSDWrGxvxmplH304jyzQmjp0AQ==",
- "dev": true
- },
- "node_modules/@types/cookiejar": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz",
- "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==",
- "dev": true
- },
- "node_modules/@types/mongodb": {
- "version": "3.6.8",
- "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.8.tgz",
- "integrity": "sha512-8qNbL5/GFrljXc/QijcuQcUMYZ1iWNcqnJ6tneROwbfU0LsAjQ9bmq3aHi5lWXM4cyBPd2F/n9INAk/pZZttHw==",
- "dependencies": {
- "@types/bson": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/node": {
- "version": "14.14.31",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz",
- "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g=="
- },
- "node_modules/@types/superagent": {
- "version": "3.8.7",
- "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-3.8.7.tgz",
- "integrity": "sha512-9KhCkyXv268A2nZ1Wvu7rQWM+BmdYUVkycFeNnYrUL5Zwu7o8wPQ3wBfW59dDP+wuoxw0ww8YKgTNv8j/cgscA==",
- "dev": true,
- "dependencies": {
- "@types/cookiejar": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@ungap/promise-all-settled": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
- "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
- "dev": true
- },
- "node_modules/abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
- },
- "node_modules/accepts": {
- "version": "1.3.7",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
- "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
- "dependencies": {
- "mime-types": "~2.1.24",
- "negotiator": "0.6.2"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "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.1",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
- "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
- "dev": true,
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/agent-base/node_modules/debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/agent-base/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/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/ansi-align": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
- "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==",
- "dependencies": {
- "string-width": "^3.0.0"
- }
- },
- "node_modules/ansi-align/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==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/ansi-align/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=="
- },
- "node_modules/ansi-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/ansi-align/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==",
- "dependencies": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/ansi-align/node_modules/strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dependencies": {
- "ansi-regex": "^4.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/ansi-colors": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
- "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
- "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/anymatch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
- "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/apidoc": {
- "version": "0.26.0",
- "resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.26.0.tgz",
- "integrity": "sha512-IEw/Z7HMMbjeVjK2sZvZSwAln8AqalLzf3qLDtkcedXVhdxGm6W7UgIW6fshegqNTMLzm8CFEMi4Lxbeu0xKTw==",
- "dependencies": {
- "apidoc-core": "^0.12.0",
- "commander": "^2.20.0",
- "fs-extra": "^9.0.1",
- "handlebars": "^4.7.6",
- "lodash": "^4.17.20",
- "markdown-it": "^11.0.0",
- "nodemon": "^2.0.4",
- "winston": "^3.3.3"
- },
- "bin": {
- "apidoc": "bin/apidoc"
- },
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/apidoc-core": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/apidoc-core/-/apidoc-core-0.12.0.tgz",
- "integrity": "sha512-VMhkJWz5IAyvWM0RnEbKNi1qe8se+id3/Ki3H/ePM8ih0KYTfaaSDxqo2w4uIVB1UVVKFvrTWyYUyQs7CEcoKQ==",
- "dependencies": {
- "fs-extra": "^9.0.1",
- "glob": "^7.1.6",
- "iconv-lite": "^0.6.2",
- "klaw-sync": "^6.0.0",
- "lodash": "^4.17.20",
- "semver": "~7.3.2"
- },
- "engines": {
- "node": ">= 0.10.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/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/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
- },
- "node_modules/assertion-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
- "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "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/async": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
- "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
- "dev": true
- },
- "node_modules/at-least-node": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
- "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
- "engines": {
- "node": ">= 4.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/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/binary-extensions": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/bl": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
- "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
- "dependencies": {
- "readable-stream": "^2.3.5",
- "safe-buffer": "^5.1.1"
- }
- },
- "node_modules/bluebird": {
- "version": "3.5.1",
- "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
- "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
- },
- "node_modules/body-parser": {
- "version": "1.19.0",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
- "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
- "dependencies": {
- "bytes": "3.1.0",
- "content-type": "~1.0.4",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "on-finished": "~2.3.0",
- "qs": "6.7.0",
- "raw-body": "2.4.0",
- "type-is": "~1.6.17"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/body-parser/node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/body-parser/node_modules/qs": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
- "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/boxen": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz",
- "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==",
- "dependencies": {
- "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"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/boxen/node_modules/chalk": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
- "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "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==",
- "dependencies": {
- "fill-range": "^7.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/browser-stdout": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
- "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
- "dev": true
- },
- "node_modules/bson": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz",
- "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==",
- "engines": {
- "node": ">=0.6.19"
- }
- },
- "node_modules/buffer-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
- },
- "node_modules/bytes": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
- "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/cacheable-request": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
- "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
- "dependencies": {
- "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"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cacheable-request/node_modules/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==",
- "dependencies": {
- "pump": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cacheable-request/node_modules/lowercase-keys": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
- "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/chai": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.0.tgz",
- "integrity": "sha512-/BFd2J30EcOwmdOgXvVsmM48l0Br0nmZPlO0uOW4XKh6kpsUumRXBgPV+IlaqFaqr9cYbeoZAM1Npx0i4A+aiA==",
- "dev": true,
- "dependencies": {
- "assertion-error": "^1.1.0",
- "check-error": "^1.0.2",
- "deep-eql": "^3.0.1",
- "get-func-name": "^2.0.0",
- "pathval": "^1.1.0",
- "type-detect": "^4.0.5"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/chai-http": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/chai-http/-/chai-http-4.3.0.tgz",
- "integrity": "sha512-zFTxlN7HLMv+7+SPXZdkd5wUlK+KxH6Q7bIEMiEx0FK3zuuMqL7cwICAQ0V1+yYRozBburYuxN1qZstgHpFZQg==",
- "dev": true,
- "dependencies": {
- "@types/chai": "4",
- "@types/superagent": "^3.8.3",
- "cookiejar": "^2.1.1",
- "is-ip": "^2.0.0",
- "methods": "^1.1.2",
- "qs": "^6.5.1",
- "superagent": "^3.7.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/chalk": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
- "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
- "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/check-error": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
- "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/chokidar": {
- "version": "3.5.1",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
- "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
- "dependencies": {
- "anymatch": "~3.1.1",
- "braces": "~3.0.2",
- "fsevents": "~2.3.1",
- "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"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.1"
- }
- },
- "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/ci-info": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
- "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
- },
- "node_modules/cli-boxes": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
- "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cli-table3": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.0.tgz",
- "integrity": "sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==",
- "dependencies": {
- "colors": "^1.1.2",
- "object-assign": "^4.1.0",
- "string-width": "^4.2.0"
- },
- "engines": {
- "node": "10.* || >= 12.*"
- },
- "optionalDependencies": {
- "colors": "^1.1.2"
- }
- },
- "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/clone-response": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
- "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
- "dependencies": {
- "mimic-response": "^1.0.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/color": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz",
- "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==",
- "dependencies": {
- "color-convert": "^1.9.1",
- "color-string": "^1.5.2"
- }
- },
- "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/color-string": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz",
- "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==",
- "dependencies": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
- }
- },
- "node_modules/color/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/color/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/colors": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
- "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
- "engines": {
- "node": ">=0.1.90"
- }
- },
- "node_modules/colorspace": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz",
- "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==",
- "dependencies": {
- "color": "3.0.x",
- "text-hex": "1.0.x"
- }
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "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/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
- },
- "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/configstore": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
- "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==",
- "dependencies": {
- "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"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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/content-disposition": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
- "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
- "dependencies": {
- "safe-buffer": "5.1.2"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
- "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
- },
- "node_modules/cookiejar": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
- "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==",
- "dev": true
- },
- "node_modules/core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
- },
- "node_modules/cors": {
- "version": "2.8.5",
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
- "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
- "dependencies": {
- "object-assign": "^4",
- "vary": "^1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "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/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==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cssfilter": {
- "version": "0.0.10",
- "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz",
- "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4="
- },
- "node_modules/date-fns": {
- "version": "2.18.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.18.0.tgz",
- "integrity": "sha512-NYyAg4wRmGVU4miKq5ivRACOODdZRY3q5WLmOJSq8djyzftYphU7dTHLcEtLqEvfqMKQ0jVv91P4BAwIjsXIcw==",
- "engines": {
- "node": ">=0.11"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/date-fns"
- }
- },
- "node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/decamelize": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
- "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/decompress-response": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
- "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
- "dependencies": {
- "mimic-response": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/deep-eql": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
- "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
- "dev": true,
- "dependencies": {
- "type-detect": "^4.0.0"
- },
- "engines": {
- "node": ">=0.12"
- }
- },
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/deep-is": {
- "version": "0.1.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==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/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=="
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
- },
- "node_modules/denque": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
- "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==",
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/depd": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
- "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/destroy": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
- "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
- },
- "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/diff": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
- "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
- "dev": true,
- "engines": {
- "node": ">=0.3.1"
- }
- },
- "node_modules/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/dot-prop": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
- "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
- "dependencies": {
- "is-obj": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dotenv": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
- "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/duplexer3": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
- "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
- },
- "node_modules/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
- },
- "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/enabled": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
- "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
- },
- "node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "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/entities": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
- "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
- },
- "node_modules/escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/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==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint": {
- "version": "7.21.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.21.0.tgz",
- "integrity": "sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "7.12.11",
- "@eslint/eslintrc": "^0.4.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",
- "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",
- "file-entry-cache": "^6.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.0.0",
- "globals": "^12.1.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": "^4.17.20",
- "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.4",
- "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-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-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-visitor-keys": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
- "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/eslint/node_modules/debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dev": true,
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/eslint/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==",
- "dev": true
- },
- "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==",
- "dev": true,
- "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/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/express": {
- "version": "4.17.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
- "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
- "dependencies": {
- "accepts": "~1.3.7",
- "array-flatten": "1.1.1",
- "body-parser": "1.19.0",
- "content-disposition": "0.5.3",
- "content-type": "~1.0.4",
- "cookie": "0.4.0",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "~1.1.2",
- "fresh": "0.5.2",
- "merge-descriptors": "1.0.1",
- "methods": "~1.1.2",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
- "proxy-addr": "~2.0.5",
- "qs": "6.7.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.1.2",
- "send": "0.17.1",
- "serve-static": "1.14.1",
- "setprototypeof": "1.1.1",
- "statuses": "~1.5.0",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/express-rate-limit": {
- "version": "5.2.6",
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.2.6.tgz",
- "integrity": "sha512-nE96xaxGfxiS5jP3tD3kIW1Jg9yQgX0rXCs3rCkZtmbWHEGyotwaezkLj7bnB41Z0uaOLM8W4AX6qHao4IZ2YA=="
- },
- "node_modules/express-validator": {
- "version": "6.10.0",
- "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.10.0.tgz",
- "integrity": "sha512-gDtepU94EpUzgFvKO/8JzjZ4uqIF4xHekjYtcNgFDiBK6Hob3MQhPU8s/c3NaWd1xi5e5nA0oVmOJ0b0ZBO36Q==",
- "dependencies": {
- "lodash": "^4.17.20",
- "validator": "^13.5.2"
- },
- "engines": {
- "node": ">= 8.0.0"
- }
- },
- "node_modules/express/node_modules/cookie": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
- "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/express/node_modules/qs": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
- "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "dev": true
- },
- "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-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-safe-stringify": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
- "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
- },
- "node_modules/fecha": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz",
- "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg=="
- },
- "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==",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/finalhandler": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
- "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "statuses": "~1.5.0",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/flat": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
- "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
- "dev": true,
- "bin": {
- "flat": "cli.js"
- }
- },
- "node_modules/flat-cache": {
- "version": "3.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/flatted": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
- "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
- "dev": true
- },
- "node_modules/fn-args": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/fn-args/-/fn-args-5.0.0.tgz",
- "integrity": "sha512-CtbfI3oFFc3nbdIoHycrfbrxiGgxXBXXuyOl49h47JawM1mYrqpiRqnH5CB2mBatdXvHHOUO6a+RiAuuvKt0lw==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/fn.name": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
- "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
- },
- "node_modules/form-data": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
- "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
- "dev": true,
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.6",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 0.12"
- }
- },
- "node_modules/formidable": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
- "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==",
- "dev": true,
- "funding": {
- "url": "https://ko-fi.com/tunnckoCore/commissions"
- }
- },
- "node_modules/forwarded": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
- "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fs-extra": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
- "dependencies": {
- "at-least-node": "^1.0.0",
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/fs-minipass": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
- "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "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==",
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "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/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==",
- "dev": true,
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-func-name": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
- "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/get-stream": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
- "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
- "dependencies": {
- "pump": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "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.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/global-dirs": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz",
- "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==",
- "dependencies": {
- "ini": "1.3.7"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/globals": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
- "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
- "dev": true,
- "dependencies": {
- "type-fest": "^0.8.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/got": {
- "version": "9.6.0",
- "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
- "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
- "dependencies": {
- "@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"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
- "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
- },
- "node_modules/growl": {
- "version": "1.10.5",
- "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
- "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
- "dev": true,
- "engines": {
- "node": ">=4.x"
- }
- },
- "node_modules/handlebars": {
- "version": "4.7.7",
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
- "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
- "dependencies": {
- "minimist": "^1.2.5",
- "neo-async": "^2.6.0",
- "source-map": "^0.6.1",
- "uglify-js": "^3.1.4",
- "wordwrap": "^1.0.0"
- },
- "bin": {
- "handlebars": "bin/handlebars"
- },
- "engines": {
- "node": ">=0.4.7"
- },
- "optionalDependencies": {
- "uglify-js": "^3.1.4"
- }
- },
- "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/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/has-yarn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
- "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/he": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
- "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
- "dev": true,
- "bin": {
- "he": "bin/he"
- }
- },
- "node_modules/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=="
- },
- "node_modules/http-errors": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
- "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
- "dependencies": {
- "depd": "~1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.1",
- "statuses": ">= 1.5.0 < 2",
- "toidentifier": "1.0.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/http-errors/node_modules/inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
- },
- "node_modules/http-proxy-agent": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
- "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
- "dependencies": {
- "@tootallnate/once": "1",
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/http-proxy-agent/node_modules/debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/http-proxy-agent/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/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/https-proxy-agent/node_modules/debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/https-proxy-agent/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/iconv-lite": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
- "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "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/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="
- },
- "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-lazy": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
- "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
- "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/ini": {
- "version": "1.3.7",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz",
- "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ=="
- },
- "node_modules/ip-regex": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
- "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/is-arrayish": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
- },
- "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==",
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-ci": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
- "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
- "dependencies": {
- "ci-info": "^2.0.0"
- },
- "bin": {
- "is-ci": "bin.js"
- }
- },
- "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=",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
- "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/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==",
- "dependencies": {
- "global-dirs": "^2.0.1",
- "is-path-inside": "^3.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-ip": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-2.0.0.tgz",
- "integrity": "sha1-aO6gfooKCpTC0IDdZ0xzGrKkYas=",
- "dev": true,
- "dependencies": {
- "ip-regex": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/is-npm": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz",
- "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==",
- "engines": {
- "node": ">=8"
- }
- },
- "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==",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-obj": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
- "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/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==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-plain-obj": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
- "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
- "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-typedarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
- },
- "node_modules/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=="
- },
- "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/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==",
- "dev": true,
- "dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/json-buffer": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
- "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg="
- },
- "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/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "dependencies": {
- "graceful-fs": "^4.1.6",
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/jsonwebtoken": {
- "version": "8.5.1",
- "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
- "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
- "dependencies": {
- "jws": "^3.2.2",
- "lodash.includes": "^4.3.0",
- "lodash.isboolean": "^3.0.3",
- "lodash.isinteger": "^4.0.4",
- "lodash.isnumber": "^3.0.3",
- "lodash.isplainobject": "^4.0.6",
- "lodash.isstring": "^4.0.1",
- "lodash.once": "^4.0.0",
- "ms": "^2.1.1",
- "semver": "^5.6.0"
- },
- "engines": {
- "node": ">=4",
- "npm": ">=1.4.28"
- }
- },
- "node_modules/jsonwebtoken/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/jsonwebtoken/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/jwa": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
- "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
- "dependencies": {
- "buffer-equal-constant-time": "1.0.1",
- "ecdsa-sig-formatter": "1.0.11",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/jws": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
- "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
- "dependencies": {
- "jwa": "^1.4.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/kareem": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz",
- "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ=="
- },
- "node_modules/keyv": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
- "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
- "dependencies": {
- "json-buffer": "3.0.0"
- }
- },
- "node_modules/klaw-sync": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
- "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
- "dependencies": {
- "graceful-fs": "^4.1.11"
- }
- },
- "node_modules/kuler": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
- "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
- },
- "node_modules/latest-version": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
- "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==",
- "dependencies": {
- "package-json": "^6.3.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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/linkify-it": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz",
- "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==",
- "dependencies": {
- "uc.micro": "^1.0.1"
- }
- },
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
- },
- "node_modules/lodash.includes": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
- "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
- },
- "node_modules/lodash.isboolean": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
- "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
- },
- "node_modules/lodash.isinteger": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
- "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
- },
- "node_modules/lodash.isnumber": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
- "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
- },
- "node_modules/lodash.isplainobject": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
- "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
- },
- "node_modules/lodash.isstring": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
- "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
- },
- "node_modules/lodash.once": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
- "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
- },
- "node_modules/log-symbols": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
- "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
- "dev": true,
- "dependencies": {
- "chalk": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/logform": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz",
- "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==",
- "dependencies": {
- "colors": "^1.2.1",
- "fast-safe-stringify": "^2.0.4",
- "fecha": "^4.2.0",
- "ms": "^2.1.1",
- "triple-beam": "^1.3.0"
- }
- },
- "node_modules/logform/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/lowercase-keys": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
- "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/lru_map": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
- "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0="
- },
- "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/markdown-it": {
- "version": "11.0.1",
- "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.1.tgz",
- "integrity": "sha512-aU1TzmBKcWNNYvH9pjq6u92BML+Hz3h5S/QpfTFwiQF852pLT+9qHsrhM9JYipkOXZxGn+sGH8oyJE9FD9WezQ==",
- "dependencies": {
- "argparse": "^1.0.7",
- "entities": "~2.0.0",
- "linkify-it": "^3.0.1",
- "mdurl": "^1.0.1",
- "uc.micro": "^1.0.5"
- },
- "bin": {
- "markdown-it": "bin/markdown-it.js"
- }
- },
- "node_modules/mdurl": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
- "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
- },
- "node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/memory-pager": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
- "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
- "optional": true
- },
- "node_modules/merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
- },
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/migrate-mongo": {
- "version": "8.1.4",
- "resolved": "https://registry.npmjs.org/migrate-mongo/-/migrate-mongo-8.1.4.tgz",
- "integrity": "sha512-iuJiG86Qzr1w9B5j6jB6akZO0w040DTEWtKdclISaQg7KdovtXGYDmW8hehDsULY5oFGjNtJv/ABsOPlz0c5mw==",
- "dependencies": {
- "cli-table3": "^0.6.0",
- "commander": "^6.1.0",
- "date-fns": "^2.16.1",
- "fn-args": "^5.0.0",
- "fs-extra": "^9.0.1",
- "lodash": "^4.17.20",
- "mongodb": "^3.6.2",
- "p-each-series": "^2.1.0"
- },
- "bin": {
- "migrate-mongo": "bin/migrate-mongo.js"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/migrate-mongo/node_modules/commander": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
- "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/mime-db": {
- "version": "1.46.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz",
- "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.29",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz",
- "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==",
- "dependencies": {
- "mime-db": "1.46.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mimic-response": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
- "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
- },
- "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/mocha": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.0.tgz",
- "integrity": "sha512-TQqyC89V1J/Vxx0DhJIXlq9gbbL9XFNdeLQ1+JsnZsVaSOV1z3tWfw0qZmQJGQRIfkvZcs7snQnZnOCKoldq1Q==",
- "dev": true,
- "dependencies": {
- "@ungap/promise-all-settled": "1.1.2",
- "ansi-colors": "4.1.1",
- "browser-stdout": "1.3.1",
- "chokidar": "3.5.1",
- "debug": "4.3.1",
- "diff": "5.0.0",
- "escape-string-regexp": "4.0.0",
- "find-up": "5.0.0",
- "glob": "7.1.6",
- "growl": "1.10.5",
- "he": "1.2.0",
- "js-yaml": "4.0.0",
- "log-symbols": "4.0.0",
- "minimatch": "3.0.4",
- "ms": "2.1.3",
- "nanoid": "3.1.20",
- "serialize-javascript": "5.0.1",
- "strip-json-comments": "3.1.1",
- "supports-color": "8.1.1",
- "which": "2.0.2",
- "wide-align": "1.1.3",
- "workerpool": "6.1.0",
- "yargs": "16.2.0",
- "yargs-parser": "20.2.4",
- "yargs-unparser": "2.0.0"
- },
- "bin": {
- "_mocha": "bin/_mocha",
- "mocha": "bin/mocha"
- },
- "engines": {
- "node": ">= 10.12.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/mochajs"
- }
- },
- "node_modules/mocha/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/mocha/node_modules/debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dev": true,
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/mocha/node_modules/debug/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==",
- "dev": true
- },
- "node_modules/mocha/node_modules/js-yaml": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz",
- "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/mocha/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
- },
- "node_modules/mocha/node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
- "node_modules/mongo-dot-notation": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/mongo-dot-notation/-/mongo-dot-notation-2.0.0.tgz",
- "integrity": "sha512-ooU9nudAGxsMiTXYvfdL8DD9ouQoK2Na1lp4IT85J7uwJuS6770Y2plhkhrl/knMFjEQ0aJqXUMc3MAcnoCHKA=="
- },
- "node_modules/mongodb": {
- "version": "3.6.4",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.4.tgz",
- "integrity": "sha512-Y+Ki9iXE9jI+n9bVtbTOOdK0B95d6wVGSucwtBkvQ+HIvVdTCfpVRp01FDC24uhC/Q2WXQ8Lpq3/zwtB5Op9Qw==",
- "dependencies": {
- "bl": "^2.2.1",
- "bson": "^1.1.4",
- "denque": "^1.4.1",
- "require_optional": "^1.0.1",
- "safe-buffer": "^5.1.2",
- "saslprep": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- },
- "optionalDependencies": {
- "saslprep": "^1.0.0"
- },
- "peerDependenciesMeta": {
- "aws4": {
- "optional": true
- },
- "bson-ext": {
- "optional": true
- },
- "kerberos": {
- "optional": true
- },
- "mongodb-client-encryption": {
- "optional": true
- },
- "mongodb-extjson": {
- "optional": true
- },
- "snappy": {
- "optional": true
- }
- }
- },
- "node_modules/mongoose": {
- "version": "5.11.18",
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.18.tgz",
- "integrity": "sha512-RsrPR9nhkXZbO3ml0DcmdbfeMvFNhgFrP81S6o1P+lFnDTNEKYnGNRCIL+ojD69wj7H5jJaAdZ0SJ5IlKxCHqw==",
- "dependencies": {
- "@types/mongodb": "^3.5.27",
- "bson": "^1.1.4",
- "kareem": "2.3.2",
- "mongodb": "3.6.4",
- "mongoose-legacy-pluralize": "1.0.2",
- "mpath": "0.8.3",
- "mquery": "3.2.4",
- "ms": "2.1.2",
- "regexp-clone": "1.0.0",
- "safe-buffer": "5.2.1",
- "sift": "7.0.1",
- "sliced": "1.0.1"
- },
- "engines": {
- "node": ">=4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/mongoose"
- }
- },
- "node_modules/mongoose-legacy-pluralize": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
- "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==",
- "peerDependencies": {
- "mongoose": "*"
- }
- },
- "node_modules/mongoose/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/mongoose/node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/mpath": {
- "version": "0.8.3",
- "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz",
- "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/mquery": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.4.tgz",
- "integrity": "sha512-uOLpp7iRX0BV1Uu6YpsqJ5b42LwYnmu0WeF/f8qgD/On3g0XDaQM6pfn0m6UxO6SM8DioZ9Bk6xxbWIGHm2zHg==",
- "dependencies": {
- "bluebird": "3.5.1",
- "debug": "3.1.0",
- "regexp-clone": "^1.0.0",
- "safe-buffer": "5.1.2",
- "sliced": "1.0.1"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/mquery/node_modules/debug": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
- },
- "node_modules/nanoid": {
- "version": "3.1.20",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
- "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==",
- "dev": true,
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "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/negotiator": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
- "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/neo-async": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
- },
- "node_modules/node-addon-api": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz",
- "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw=="
- },
- "node_modules/node-fetch": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
- "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
- "engines": {
- "node": "4.x || >=6.0.0"
- }
- },
- "node_modules/nodemon": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz",
- "integrity": "sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==",
- "hasInstallScript": true,
- "dependencies": {
- "chokidar": "^3.2.2",
- "debug": "^3.2.6",
- "ignore-by-default": "^1.0.1",
- "minimatch": "^3.0.4",
- "pstree.remy": "^1.1.7",
- "semver": "^5.7.1",
- "supports-color": "^5.5.0",
- "touch": "^3.1.0",
- "undefsafe": "^2.0.3",
- "update-notifier": "^4.1.0"
- },
- "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==",
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/nodemon/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/nodemon/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/nodemon/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/nodemon/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/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/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/normalize-url": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
- "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==",
- "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/on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
- "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "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/one-time": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
- "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
- "dependencies": {
- "fn.name": "1.x.x"
- }
- },
- "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-cancelable": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
- "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/p-each-series": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz",
- "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "dependencies": {
- "p-limit": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/package-json": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
- "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
- "dependencies": {
- "got": "^9.6.0",
- "registry-auth-token": "^4.0.0",
- "registry-url": "^5.0.0",
- "semver": "^6.2.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/package-json/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/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/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/passport": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz",
- "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==",
- "dependencies": {
- "passport-strategy": "1.x.x",
- "pause": "0.0.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/passport-http": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/passport-http/-/passport-http-0.3.0.tgz",
- "integrity": "sha1-juU9Q4C+nGDfIVGSUCmCb3cRVgM=",
- "dependencies": {
- "passport-strategy": "1.x.x"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/passport-jwt": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz",
- "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==",
- "dependencies": {
- "jsonwebtoken": "^8.2.0",
- "passport-strategy": "^1.0.0"
- }
- },
- "node_modules/passport-local": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
- "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
- "dependencies": {
- "passport-strategy": "1.x.x"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/passport-strategy": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
- "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "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-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
- },
- "node_modules/pathval": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
- "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/pause": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
- "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
- },
- "node_modules/picomatch": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
- "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "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/prepend-http": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
- "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
- "engines": {
- "node": ">=4"
- }
- },
- "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/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/proxy-addr": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
- "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
- "dependencies": {
- "forwarded": "~0.1.2",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "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=="
- },
- "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/pupa": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz",
- "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==",
- "dependencies": {
- "escape-goat": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/qs": {
- "version": "6.9.6",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
- "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==",
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/randombytes": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
- "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
- "dev": true,
- "dependencies": {
- "safe-buffer": "^5.1.0"
- }
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
- "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
- "dependencies": {
- "bytes": "3.1.0",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/raw-body/node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/rc/node_modules/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=",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "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.5.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
- "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/regexp-clone": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
- "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw=="
- },
- "node_modules/regexpp": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
- "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/mysticatea"
- }
- },
- "node_modules/registry-auth-token": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz",
- "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==",
- "dependencies": {
- "rc": "^1.2.8"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/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==",
- "dependencies": {
- "rc": "^1.2.8"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/require_optional": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
- "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
- "dependencies": {
- "resolve-from": "^2.0.0",
- "semver": "^5.1.0"
- }
- },
- "node_modules/require_optional/node_modules/resolve-from": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
- "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/require_optional/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "bin": {
- "semver": "bin/semver"
- }
- },
- "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=",
- "dev": true,
- "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/requirejs": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
- "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
- "bin": {
- "r_js": "bin/r.js",
- "r.js": "bin/r.js"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "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/responselike": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
- "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
- "dependencies": {
- "lowercase-keys": "^1.0.0"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "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/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
- },
- "node_modules/saslprep": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
- "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
- "optional": true,
- "dependencies": {
- "sparse-bitfield": "^3.0.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/semver": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
- "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/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==",
- "dependencies": {
- "semver": "^6.3.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/semver-diff/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/send": {
- "version": "0.17.1",
- "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
- "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
- "dependencies": {
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "destroy": "~1.0.4",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "~1.7.2",
- "mime": "1.6.0",
- "ms": "2.1.1",
- "on-finished": "~2.3.0",
- "range-parser": "~1.2.1",
- "statuses": "~1.5.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
- },
- "node_modules/serialize-javascript": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
- "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==",
- "dev": true,
- "dependencies": {
- "randombytes": "^2.1.0"
- }
- },
- "node_modules/serve-static": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
- "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
- "dependencies": {
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "0.17.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "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/setprototypeof": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
- "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
- },
- "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/sift": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz",
- "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g=="
- },
- "node_modules/signal-exit": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
- "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
- },
- "node_modules/simple-swizzle": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
- "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
- "dependencies": {
- "is-arrayish": "^0.3.1"
- }
- },
- "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/sliced": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
- "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
- },
- "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/sparse-bitfield": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
- "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
- "optional": true,
- "dependencies": {
- "memory-pager": "^1.0.2"
- }
- },
- "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/stack-trace": {
- "version": "0.0.10",
- "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
- "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/statuses": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
- "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "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-width": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
- "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
- "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
- "dependencies": {
- "ansi-regex": "^5.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/superagent": {
- "version": "3.8.3",
- "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
- "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
- "dev": true,
- "dependencies": {
- "component-emitter": "^1.2.0",
- "cookiejar": "^2.1.0",
- "debug": "^3.1.0",
- "extend": "^3.0.0",
- "form-data": "^2.3.1",
- "formidable": "^1.2.0",
- "methods": "^1.1.1",
- "mime": "^1.4.1",
- "qs": "^6.5.1",
- "readable-stream": "^2.3.5"
- },
- "engines": {
- "node": ">= 4.0"
- }
- },
- "node_modules/superagent/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/superagent/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
- },
- "node_modules/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/table": {
- "version": "6.0.7",
- "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
- "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
- "dev": true,
- "dependencies": {
- "ajv": "^7.0.2",
- "lodash": "^4.17.20",
- "slice-ansi": "^4.0.0",
- "string-width": "^4.2.0"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/table/node_modules/ajv": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz",
- "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==",
- "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.0",
- "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
- "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
- "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/term-size": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
- "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/text-hex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
- "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
- },
- "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/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==",
- "engines": {
- "node": ">=6"
- }
- },
- "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==",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
- "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
- "engines": {
- "node": ">=0.6"
- }
- },
- "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==",
- "dependencies": {
- "nopt": "~1.0.10"
- },
- "bin": {
- "nodetouch": "bin/nodetouch.js"
- }
- },
- "node_modules/touch/node_modules/nopt": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
- "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
- "dependencies": {
- "abbrev": "1"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- }
- },
- "node_modules/triple-beam": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
- "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
- },
- "node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "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.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/typedarray-to-buffer": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
- "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
- "dependencies": {
- "is-typedarray": "^1.0.0"
- }
- },
- "node_modules/uc.micro": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
- "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
- },
- "node_modules/uglify-js": {
- "version": "3.12.8",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz",
- "integrity": "sha512-fvBeuXOsvqjecUtF/l1dwsrrf5y2BCUk9AOJGzGcm6tE7vegku5u/YvqjyDaAGr422PLoLnrxg3EnRvTqsdC1w==",
- "optional": true,
- "bin": {
- "uglifyjs": "bin/uglifyjs"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/undefsafe": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
- "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==",
- "dependencies": {
- "debug": "^2.2.0"
- }
- },
- "node_modules/unique-string": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
- "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
- "dependencies": {
- "crypto-random-string": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/universalify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
- "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/update-notifier": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz",
- "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==",
- "dependencies": {
- "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"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/yeoman/update-notifier?sponsor=1"
- }
- },
- "node_modules/update-notifier/node_modules/chalk": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
- "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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/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=",
- "dependencies": {
- "prepend-http": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "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/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/v8-compile-cache": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz",
- "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==",
- "dev": true
- },
- "node_modules/validator": {
- "version": "13.5.2",
- "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz",
- "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "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/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/widest-line": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
- "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
- "dependencies": {
- "string-width": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/winston": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz",
- "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==",
- "dependencies": {
- "@dabh/diagnostics": "^2.0.2",
- "async": "^3.1.0",
- "is-stream": "^2.0.0",
- "logform": "^2.2.0",
- "one-time": "^1.0.0",
- "readable-stream": "^3.4.0",
- "stack-trace": "0.0.x",
- "triple-beam": "^1.3.0",
- "winston-transport": "^4.4.0"
- },
- "engines": {
- "node": ">= 6.4.0"
- }
- },
- "node_modules/winston-transport": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz",
- "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==",
- "dependencies": {
- "readable-stream": "^2.3.7",
- "triple-beam": "^1.2.0"
- },
- "engines": {
- "node": ">= 6.4.0"
- }
- },
- "node_modules/winston/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/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/wordwrap": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
- },
- "node_modules/workerpool": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz",
- "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==",
- "dev": true
- },
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "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/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
- },
- "node_modules/write-file-atomic": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
- "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
- "dependencies": {
- "imurmurhash": "^0.1.4",
- "is-typedarray": "^1.0.0",
- "signal-exit": "^3.0.2",
- "typedarray-to-buffer": "^3.1.5"
- }
- },
- "node_modules/xdg-basedir": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
- "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/xss": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.8.tgz",
- "integrity": "sha512-3MgPdaXV8rfQ/pNn16Eio6VXYPTkqwa0vc7GkiymmY/DqR1SE/7VPAAVZz1GJsJFrllMYO3RHfEaiUGjab6TNw==",
- "dependencies": {
- "commander": "^2.20.3",
- "cssfilter": "0.0.10"
- },
- "bin": {
- "xss": "bin/xss"
- },
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/y18n": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
- "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "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": "16.2.0",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
- "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
- "dev": true,
- "dependencies": {
- "cliui": "^7.0.2",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.0",
- "y18n": "^5.0.5",
- "yargs-parser": "^20.2.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yargs-parser": {
- "version": "20.2.4",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
- "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yargs-unparser": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
- "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
- "dev": true,
- "dependencies": {
- "camelcase": "^6.0.0",
- "decamelize": "^4.0.0",
- "flat": "^5.0.2",
- "is-plain-obj": "^2.1.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yargs-unparser/node_modules/camelcase": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz",
- "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- }
- },
"dependencies": {
"@babel/code-frame": {
"version": "7.12.11",
@@ -4908,9 +20,9 @@
"dev": true
},
"@babel/highlight": {
- "version": "7.13.8",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.8.tgz",
- "integrity": "sha512-4vrIhfJyfNf+lCtXC2ck1rKSzDwciqF7IWFhXXrSOUC2O5DrVp+w4c6ed4AllTxhTkUP5x2tYj41VaxdVMMRDw==",
+ "version": "7.13.10",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz",
+ "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.12.11",
@@ -5012,6 +124,15 @@
"ms": "2.1.2"
}
},
+ "globals": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+ "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.8.1"
+ }
+ },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -5021,13 +142,13 @@
}
},
"@mapbox/node-pre-gyp": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.0.tgz",
- "integrity": "sha512-mEaiD1CURETR/dBIiJAwz0M0Q0mH3gCW4pPMaIlNt97mdzYUVeqGcTJSamgJpS6Tg4tBHDrOJpjdh5fJTLnyNQ==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.1.tgz",
+ "integrity": "sha512-CUBdThIZMoLEQQxACwhLsPg/puxBca0abTH3ixuvBQkhjJ80Hdp99jmVjxFCOa52/tZqN9d70IbGUf+OuKDHGA==",
"requires": {
"detect-libc": "^1.0.3",
"http-proxy-agent": "^4.0.1",
- "mkdirp": "^1.0.4",
+ "make-dir": "^3.1.0",
"node-fetch": "^2.6.1",
"nopt": "^5.0.0",
"npmlog": "^4.1.2",
@@ -5037,47 +158,47 @@
}
},
"@sentry/core": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.2.1.tgz",
- "integrity": "sha512-jPqQEtafxxDtLONhCbTHh/Uq8mZRhsfbwJTSVYfPVEe/ELfFZLQK7tP6rOh7zEWKbTkE0mE6XcaoH3ZRAhgrqg==",
- "requires": {
- "@sentry/hub": "6.2.1",
- "@sentry/minimal": "6.2.1",
- "@sentry/types": "6.2.1",
- "@sentry/utils": "6.2.1",
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.3.5.tgz",
+ "integrity": "sha512-VR2ibDy33mryD0mT6d9fGhKjdNzS2FSwwZPe9GvmNOjkyjly/oV91BKVoYJneCqOeq8fyj2lvkJGKuupdJNDqg==",
+ "requires": {
+ "@sentry/hub": "6.3.5",
+ "@sentry/minimal": "6.3.5",
+ "@sentry/types": "6.3.5",
+ "@sentry/utils": "6.3.5",
"tslib": "^1.9.3"
}
},
"@sentry/hub": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.1.tgz",
- "integrity": "sha512-pG7wCQeRpzeP6t0bT4T0X029R19dbDS3/qswF8BL6bg0AI3afjfjBAZm/fqn1Uwe/uBoMHVVdbxgJDZeQ5d4rQ==",
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.5.tgz",
+ "integrity": "sha512-ZYFo7VYKwdPVjuV9BDFiYn+MpANn6eZMz5QDBfZ2dugIvIVbuOyOOLx8PSa3ZXJoVTZZ7s2wD2fi/ZxKjNjZOQ==",
"requires": {
- "@sentry/types": "6.2.1",
- "@sentry/utils": "6.2.1",
+ "@sentry/types": "6.3.5",
+ "@sentry/utils": "6.3.5",
"tslib": "^1.9.3"
}
},
"@sentry/minimal": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.1.tgz",
- "integrity": "sha512-wuSXB4Ayxv9rBEQ4pm7fnG4UU2ZPtPnnChoEfd4/mw1UthXSvmPFEn6O4pdo2G8fTkl8eqm6wT/Q7uIXMEmw+A==",
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.5.tgz",
+ "integrity": "sha512-4RqIGAU0+8iI/1sw0GYPTr4SUA88/i2+JPjFJ+qloh5ANVaNwhFPRChw+Ys9xpre8LV9JZrEsEf8AvQr4fkNbA==",
"requires": {
- "@sentry/hub": "6.2.1",
- "@sentry/types": "6.2.1",
+ "@sentry/hub": "6.3.5",
+ "@sentry/types": "6.3.5",
"tslib": "^1.9.3"
}
},
"@sentry/node": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.2.1.tgz",
- "integrity": "sha512-JlixtJHS6xMzh2G4Pz7oMM8Nd40mGUALQYtuGMwW2QE3IduOaaGsn1+eVpN6PwZetMnvRIn6VVFOc2UmFIzWpA==",
- "requires": {
- "@sentry/core": "6.2.1",
- "@sentry/hub": "6.2.1",
- "@sentry/tracing": "6.2.1",
- "@sentry/types": "6.2.1",
- "@sentry/utils": "6.2.1",
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.3.5.tgz",
+ "integrity": "sha512-scPB+DoAEPaqkYuyb8d/gVWbFmX5PhaYSNHybeHncaP/P4itLdq/AoAWGNxl0Hj4EQokfT4OZWxaaJi7SCYnaw==",
+ "requires": {
+ "@sentry/core": "6.3.5",
+ "@sentry/hub": "6.3.5",
+ "@sentry/tracing": "6.3.5",
+ "@sentry/types": "6.3.5",
+ "@sentry/utils": "6.3.5",
"cookie": "^0.4.1",
"https-proxy-agent": "^5.0.0",
"lru_map": "^0.3.3",
@@ -5085,28 +206,28 @@
}
},
"@sentry/tracing": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.2.1.tgz",
- "integrity": "sha512-bvStY1SnL08wkSeVK3j9K5rivQQJdKFCPR2VYRFOCaUoleZ6ChPUnBvxQ/E2LXc0hk/y/wo1q4r5B0dfCCY+bQ==",
- "requires": {
- "@sentry/hub": "6.2.1",
- "@sentry/minimal": "6.2.1",
- "@sentry/types": "6.2.1",
- "@sentry/utils": "6.2.1",
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.3.5.tgz",
+ "integrity": "sha512-TNKAST1ge2g24BlTfVxNp4gP5t3drbi0OVCh8h8ah+J7UjHSfdiqhd9W2h5qv1GO61gGlpWeN/TyioyQmOxu0Q==",
+ "requires": {
+ "@sentry/hub": "6.3.5",
+ "@sentry/minimal": "6.3.5",
+ "@sentry/types": "6.3.5",
+ "@sentry/utils": "6.3.5",
"tslib": "^1.9.3"
}
},
"@sentry/types": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.1.tgz",
- "integrity": "sha512-h0OV1QT+fv5ojfK5/+iEXClu33HirmvbjcQC2jf05IHj9yXIOWy6EB10S8nBjuLiiFqQiAQYj3FN9Ip4eN8NJA=="
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz",
+ "integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ=="
},
"@sentry/utils": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.1.tgz",
- "integrity": "sha512-6kQgM/yBPdXu+3qbJnI6HBcWztN9QfiMkH++ZiKk4ERhg9d2LYWlze478uTU5Fyo/JQYcp+McpjtjpR9QIrr0g==",
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz",
+ "integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==",
"requires": {
- "@sentry/types": "6.2.1",
+ "@sentry/types": "6.3.5",
"tslib": "^1.9.3"
}
},
@@ -5149,18 +270,18 @@
"dev": true
},
"@types/mongodb": {
- "version": "3.6.8",
- "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.8.tgz",
- "integrity": "sha512-8qNbL5/GFrljXc/QijcuQcUMYZ1iWNcqnJ6tneROwbfU0LsAjQ9bmq3aHi5lWXM4cyBPd2F/n9INAk/pZZttHw==",
+ "version": "3.6.12",
+ "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.12.tgz",
+ "integrity": "sha512-49aEzQD5VdHPxyd5dRyQdqEveAg9LanwrH8RQipnMuulwzKmODXIZRp0umtxi1eBUfEusRkoy8AVOMr+kVuFog==",
"requires": {
"@types/bson": "*",
"@types/node": "*"
}
},
"@types/node": {
- "version": "14.14.31",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz",
- "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g=="
+ "version": "14.14.36",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.36.tgz",
+ "integrity": "sha512-kjivUwDJfIjngzbhooRnOLhGYz6oRFi+L+EpMjxroDYXwDw9lHrJJ43E+dJ6KAd3V3WxWAJ/qZE9XKYHhjPOFQ=="
},
"@types/superagent": {
"version": "3.8.7",
@@ -5202,8 +323,7 @@
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"agent-base": {
"version": "6.0.2",
@@ -5394,6 +514,14 @@
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
},
+ "axios": {
+ "version": "0.21.1",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
+ "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
+ "requires": {
+ "follow-redirects": "^1.10.0"
+ }
+ },
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -5482,6 +610,11 @@
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
}
}
},
@@ -5509,9 +642,9 @@
"dev": true
},
"bson": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz",
- "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg=="
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
+ "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg=="
},
"buffer-equal-constant-time": {
"version": "1.0.1",
@@ -5552,6 +685,15 @@
}
}
},
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "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",
@@ -5564,16 +706,16 @@
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"chai": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.0.tgz",
- "integrity": "sha512-/BFd2J30EcOwmdOgXvVsmM48l0Br0nmZPlO0uOW4XKh6kpsUumRXBgPV+IlaqFaqr9cYbeoZAM1Npx0i4A+aiA==",
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz",
+ "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==",
"dev": true,
"requires": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
"deep-eql": "^3.0.1",
"get-func-name": "^2.0.0",
- "pathval": "^1.1.0",
+ "pathval": "^1.1.1",
"type-detect": "^4.0.5"
}
},
@@ -5710,9 +852,9 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"color-string": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz",
- "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==",
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz",
+ "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@@ -5840,9 +982,9 @@
"integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4="
},
"date-fns": {
- "version": "2.18.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.18.0.tgz",
- "integrity": "sha512-NYyAg4wRmGVU4miKq5ivRACOODdZRY3q5WLmOJSq8djyzftYphU7dTHLcEtLqEvfqMKQ0jVv91P4BAwIjsXIcw=="
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.19.0.tgz",
+ "integrity": "sha512-X3bf2iTPgCAQp9wvjOQytnf5vO5rESYRXlPIVcgSbtT5OTScPcsf9eZU+B/YIkKAtYr5WeCii58BgATrNitlWg=="
},
"debug": {
"version": "2.6.9",
@@ -6033,9 +1175,9 @@
"dev": true
},
"eslint": {
- "version": "7.21.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.21.0.tgz",
- "integrity": "sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==",
+ "version": "7.25.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz",
+ "integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==",
"dev": true,
"requires": {
"@babel/code-frame": "7.12.11",
@@ -6055,7 +1197,7 @@
"file-entry-cache": "^6.0.1",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^5.0.0",
- "globals": "^12.1.0",
+ "globals": "^13.6.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
@@ -6063,7 +1205,7 @@
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
- "lodash": "^4.17.20",
+ "lodash": "^4.17.21",
"minimatch": "^3.0.4",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
@@ -6258,11 +1400,11 @@
"integrity": "sha512-nE96xaxGfxiS5jP3tD3kIW1Jg9yQgX0rXCs3rCkZtmbWHEGyotwaezkLj7bnB41Z0uaOLM8W4AX6qHao4IZ2YA=="
},
"express-validator": {
- "version": "6.10.0",
- "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.10.0.tgz",
- "integrity": "sha512-gDtepU94EpUzgFvKO/8JzjZ4uqIF4xHekjYtcNgFDiBK6Hob3MQhPU8s/c3NaWd1xi5e5nA0oVmOJ0b0ZBO36Q==",
+ "version": "6.10.1",
+ "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.10.1.tgz",
+ "integrity": "sha512-joYSJdkUyKMZ2gAUvyQNmqJ7x1vhrC/IHCKWauhKfoXNF83j65KnlqEEXXynBnJRd0QrNZ/aXw9uIhS6ptG0Cg==",
"requires": {
- "lodash": "^4.17.20",
+ "lodash": "^4.17.21",
"validator": "^13.5.2"
}
},
@@ -6296,9 +1438,9 @@
"integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
},
"fecha": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz",
- "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg=="
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz",
+ "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q=="
},
"file-entry-cache": {
"version": "6.0.1",
@@ -6373,6 +1515,11 @@
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
+ "follow-redirects": {
+ "version": "1.13.3",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz",
+ "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA=="
+ },
"form-data": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
@@ -6430,6 +1577,11 @@
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"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",
@@ -6496,6 +1648,16 @@
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
"dev": true
},
+ "get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ }
+ },
"get-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
@@ -6518,9 +1680,9 @@
}
},
"glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"requires": {
"is-glob": "^4.0.1"
}
@@ -6534,12 +1696,20 @@
}
},
"globals": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
- "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "version": "13.8.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz",
+ "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==",
"dev": true,
"requires": {
- "type-fest": "^0.8.1"
+ "type-fest": "^0.20.2"
+ },
+ "dependencies": {
+ "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
+ }
}
},
"got": {
@@ -6583,11 +1753,24 @@
"wordwrap": "^1.0.0"
}
},
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
+ "has-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
+ },
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@@ -6819,9 +2002,9 @@
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
},
"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=="
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="
},
"is-plain-obj": {
"version": "2.1.0",
@@ -7011,6 +2194,18 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "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
+ },
+ "lodash.flatten": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+ "dev": true
+ },
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -7046,6 +2241,12 @@
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
+ "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
+ },
"log-symbols": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
@@ -7079,11 +2280,6 @@
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
"integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
},
- "lru_map": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
- "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0="
- },
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -7092,6 +2288,11 @@
"yallist": "^4.0.0"
}
},
+ "lru_map": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
+ "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0="
+ },
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -7146,24 +2347,24 @@
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"migrate-mongo": {
- "version": "8.1.4",
- "resolved": "https://registry.npmjs.org/migrate-mongo/-/migrate-mongo-8.1.4.tgz",
- "integrity": "sha512-iuJiG86Qzr1w9B5j6jB6akZO0w040DTEWtKdclISaQg7KdovtXGYDmW8hehDsULY5oFGjNtJv/ABsOPlz0c5mw==",
+ "version": "8.2.2",
+ "resolved": "https://registry.npmjs.org/migrate-mongo/-/migrate-mongo-8.2.2.tgz",
+ "integrity": "sha512-RK8zE9QGzaDZ8xN+Cyb/mUhSIA1pkj1Q/aNYeH4QB9U2UNfKej1lmxh20Ot1xFl1C62ro3hqiaZ9QErzCN3qPw==",
"requires": {
"cli-table3": "^0.6.0",
- "commander": "^6.1.0",
- "date-fns": "^2.16.1",
+ "commander": "^7.1.0",
+ "date-fns": "^2.19.0",
"fn-args": "^5.0.0",
- "fs-extra": "^9.0.1",
- "lodash": "^4.17.20",
- "mongodb": "^3.6.2",
- "p-each-series": "^2.1.0"
+ "fs-extra": "^9.1.0",
+ "lodash": "^4.17.21",
+ "mongodb": "^3.6.4",
+ "p-each-series": "^2.2.0"
},
"dependencies": {
"commander": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
- "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
}
}
},
@@ -7226,9 +2427,9 @@
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
},
"mocha": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.0.tgz",
- "integrity": "sha512-TQqyC89V1J/Vxx0DhJIXlq9gbbL9XFNdeLQ1+JsnZsVaSOV1z3tWfw0qZmQJGQRIfkvZcs7snQnZnOCKoldq1Q==",
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz",
+ "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==",
"dev": true,
"requires": {
"@ungap/promise-all-settled": "1.1.2",
@@ -7313,9 +2514,9 @@
"integrity": "sha512-ooU9nudAGxsMiTXYvfdL8DD9ouQoK2Na1lp4IT85J7uwJuS6770Y2plhkhrl/knMFjEQ0aJqXUMc3MAcnoCHKA=="
},
"mongodb": {
- "version": "3.6.4",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.4.tgz",
- "integrity": "sha512-Y+Ki9iXE9jI+n9bVtbTOOdK0B95d6wVGSucwtBkvQ+HIvVdTCfpVRp01FDC24uhC/Q2WXQ8Lpq3/zwtB5Op9Qw==",
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.5.tgz",
+ "integrity": "sha512-mQlYKw1iGbvJJejcPuyTaytq0xxlYbIoVDm2FODR+OHxyEiMR021vc32bTvamgBjCswsD54XIRwhg3yBaWqJjg==",
"requires": {
"bl": "^2.2.1",
"bson": "^1.1.4",
@@ -7326,17 +2527,17 @@
}
},
"mongoose": {
- "version": "5.11.18",
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.18.tgz",
- "integrity": "sha512-RsrPR9nhkXZbO3ml0DcmdbfeMvFNhgFrP81S6o1P+lFnDTNEKYnGNRCIL+ojD69wj7H5jJaAdZ0SJ5IlKxCHqw==",
+ "version": "5.12.5",
+ "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.12.5.tgz",
+ "integrity": "sha512-VVoqiELZcoI2HhHDuPpfN3qmExrtIeXSWNb1nihf4w1SJoWGXilU/g2cQgeeSMc2vAHSZd5Nv2sNPvbZHFw+pg==",
"requires": {
"@types/mongodb": "^3.5.27",
"bson": "^1.1.4",
"kareem": "2.3.2",
- "mongodb": "3.6.4",
+ "mongodb": "3.6.6",
"mongoose-legacy-pluralize": "1.0.2",
"mpath": "0.8.3",
- "mquery": "3.2.4",
+ "mquery": "3.2.5",
"ms": "2.1.2",
"regexp-clone": "1.0.0",
"safe-buffer": "5.2.1",
@@ -7344,6 +2545,19 @@
"sliced": "1.0.1"
},
"dependencies": {
+ "mongodb": {
+ "version": "3.6.6",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.6.tgz",
+ "integrity": "sha512-WlirMiuV1UPbej5JeCMqE93JRfZ/ZzqE7nJTwP85XzjAF4rRSeq2bGCb1cjfoHLOF06+HxADaPGqT0g3SbVT1w==",
+ "requires": {
+ "bl": "^2.2.1",
+ "bson": "^1.1.4",
+ "denque": "^1.4.1",
+ "optional-require": "^1.0.2",
+ "safe-buffer": "^5.1.2",
+ "saslprep": "^1.0.0"
+ }
+ },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -7359,8 +2573,7 @@
"mongoose-legacy-pluralize": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
- "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==",
- "requires": {}
+ "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ=="
},
"mpath": {
"version": "0.8.3",
@@ -7368,9 +2581,9 @@
"integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA=="
},
"mquery": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.4.tgz",
- "integrity": "sha512-uOLpp7iRX0BV1Uu6YpsqJ5b42LwYnmu0WeF/f8qgD/On3g0XDaQM6pfn0m6UxO6SM8DioZ9Bk6xxbWIGHm2zHg==",
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz",
+ "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==",
"requires": {
"bluebird": "3.5.1",
"debug": "3.1.0",
@@ -7515,6 +2728,11 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
+ "object-inspect": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
+ "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw=="
+ },
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -7539,6 +2757,11 @@
"fn.name": "1.x.x"
}
},
+ "optional-require": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
+ "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA=="
+ },
"optionator": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@@ -7750,9 +2973,12 @@
}
},
"qs": {
- "version": "6.9.6",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz",
- "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ=="
+ "version": "6.10.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
+ "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
+ "requires": {
+ "side-channel": "^1.0.4"
+ }
},
"randombytes": {
"version": "2.1.0",
@@ -7856,6 +3082,18 @@
"rc": "^1.2.8"
}
},
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "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
+ },
"require_optional": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
@@ -7877,18 +3115,6 @@
}
}
},
- "require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
- "dev": true
- },
- "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
- },
"requirejs": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
@@ -7936,9 +3162,9 @@
}
},
"semver": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
- "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+ "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"
}
@@ -8030,6 +3256,16 @@
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
"sift": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz",
@@ -8093,14 +3329,6 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
- "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-width": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
@@ -8111,6 +3339,14 @@
"strip-ansi": "^6.0.0"
}
},
+ "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"
+ }
+ },
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
@@ -8169,21 +3405,24 @@
}
},
"table": {
- "version": "6.0.7",
- "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz",
- "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==",
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.6.0.tgz",
+ "integrity": "sha512-iZMtp5tUvcnAdtHpZTWLPF0M7AgiQsURR2DwmxnJwSy8I3+cY+ozzVvYha3BOLG2TB+L0CqjIz+91htuj6yCXg==",
"dev": true,
"requires": {
- "ajv": "^7.0.2",
- "lodash": "^4.17.20",
+ "ajv": "^8.0.1",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.flatten": "^4.4.0",
+ "lodash.truncate": "^4.4.2",
"slice-ansi": "^4.0.0",
- "string-width": "^4.2.0"
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0"
},
"dependencies": {
"ajv": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz",
- "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.1.0.tgz",
+ "integrity": "sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@@ -8293,7 +3532,8 @@
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
},
"type-is": {
"version": "1.6.18",
@@ -8318,9 +3558,9 @@
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
"uglify-js": {
- "version": "3.12.8",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz",
- "integrity": "sha512-fvBeuXOsvqjecUtF/l1dwsrrf5y2BCUk9AOJGzGcm6tE7vegku5u/YvqjyDaAGr422PLoLnrxg3EnRvTqsdC1w==",
+ "version": "3.13.4",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.4.tgz",
+ "integrity": "sha512-kv7fCkIXyQIilD5/yQy8O+uagsYIOt5cZvs890W40/e/rvjMSzJw81o9Bg0tkURxzZBROtDQhW2LFjOGoK3RZw==",
"optional": true
},
"undefsafe": {
@@ -8408,15 +3648,15 @@
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"v8-compile-cache": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz",
- "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==",
+ "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
},
"validator": {
- "version": "13.5.2",
- "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz",
- "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ=="
+ "version": "13.6.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.6.0.tgz",
+ "integrity": "sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg=="
},
"vary": {
"version": "1.1.2",
diff --git a/package.json b/package.json
index 4248e72..c9fcabd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "werewolwes-assistant-api",
- "version": "0.10.0",
+ "version": "0.11.0",
"description": "Back end for the werewolves assistant",
"main": "app.js",
"scripts": {
@@ -29,13 +29,14 @@
"devDependencies": {
"chai": "^4.2.0",
"chai-http": "^4.3.0",
- "eslint": "^7.19.0",
+ "eslint": "^7.25.0",
"mocha": "^8.2.1",
"nodemon": "^2.0.7"
},
"dependencies": {
- "@sentry/node": "^6.0.3",
+ "@sentry/node": "^6.3.5",
"apidoc": "^0.26.0",
+ "axios": "^0.21.1",
"bcrypt": "^5.0.0",
"body-parser": "^1.19.0",
"colors": "^1.4.0",
@@ -44,18 +45,18 @@
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-rate-limit": "^5.2.3",
- "express-validator": "^6.9.2",
+ "express-validator": "^6.10.1",
"jsonwebtoken": "^8.5.1",
"migrate-mongo": "^8.1.4",
"mongo-dot-notation": "^2.0.0",
- "mongoose": "^5.11.14",
+ "mongoose": "5.12.5",
"passport": "^0.4.1",
"passport-http": "^0.3.0",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"qs": "^6.9.6",
"requirejs": "^2.3.6",
- "validator": "^13.5.2",
+ "validator": "^13.6.0",
"xss": "^1.0.8"
}
}
diff --git a/src/controllers/Game.js b/src/controllers/Game.js
index 6e0b7aa..0cbe7d0 100755
--- a/src/controllers/Game.js
+++ b/src/controllers/Game.js
@@ -64,15 +64,20 @@ exports.fillTickData = game => {
game.turn = 1;
};
-exports.checkAdditionalCardsData = ({ players, additionalCards }) => {
+exports.checkAdditionalCardsData = ({ players, additionalCards, options }) => {
+ const { additionalCardsCount: thiefAdditionalCardsCount } = options.roles.thief;
if (additionalCards && !getPlayerWithRole("thief", { players })) {
throw generateError("ADDITIONAL_CARDS_NOT_ALLOWED", "`additionalCards` is not allowed when there is no `thief` in game.");
} else if (!additionalCards && getPlayerWithRole("thief", { players })) {
- throw generateError("NEED_ADDITIONAL_CARDS_FOR_THIEF", "2 additional cards are needed for thief.");
+ throw generateError("NEED_ADDITIONAL_CARDS_FOR_THIEF", `${thiefAdditionalCardsCount} additional cards are needed for thief.`);
}
if (additionalCards) {
const additionalCardsThiefRoleNames = getAdditionalCardsThiefRoleNames();
const roles = getRoles();
+ const thiefAdditionalCards = additionalCards.filter(({ for: recipient }) => recipient === "thief");
+ if (thiefAdditionalCards.length !== thiefAdditionalCardsCount) {
+ throw generateError("THIEF_ADDITIONAL_CARDS_COUNT_NOT_RESPECTED", `Exactly ${thiefAdditionalCardsCount} additional cards are needed for thief.`);
+ }
for (const { role: additionalRole, for: recipient } of additionalCards) {
if (recipient === "thief" && !additionalCardsThiefRoleNames.includes(additionalRole)) {
throw generateError("FORBIDDEN_ADDITIONAL_CARD_ROLE_FOR_THIEF", `"${additionalRole}" is not allowed in additional cards for thief.`);
@@ -107,6 +112,7 @@ exports.checkRolesCompatibility = players => {
};
exports.fillPlayersData = players => {
+ let position = 0;
for (const player of players) {
player.name = filterOutHTMLTags(player.name);
const role = getRoles().find(playerRole => playerRole.name === player.role);
@@ -115,13 +121,33 @@ exports.fillPlayersData = players => {
if (role.name === "villager-villager") {
player.role.isRevealed = true;
}
+ if (player.position === undefined) {
+ player.position = position;
+ }
player.isAlive = true;
+ position++;
+ }
+ players.sort((a, b) => a.position > b.position ? 1 : -1);
+};
+
+exports.checkPlayersPosition = players => {
+ const isOnePlayerPositionNotSet = !!players.find(({ position }) => position === undefined);
+ if (isOnePlayerPositionNotSet && !!players.find(({ position }) => position !== undefined)) {
+ throw generateError("ALL_PLAYERS_POSITION_NOT_SET", `Some players has a position and other not. You must define all position or none of them.`);
+ } else if (!isOnePlayerPositionNotSet) {
+ const playerPositionSet = [...new Set(players.map(({ position }) => position))];
+ const playerMaxPosition = players.length - 1;
+ if (playerPositionSet.length !== players.length) {
+ throw generateError("PLAYERS_POSITION_NOT_UNIQUE", "Players don't all have unique position.");
+ } else if (players.some(({ position }) => position > playerMaxPosition)) {
+ throw generateError("PLAYER_POSITION_TOO_HIGH", `One player's position exceeds the maximum (${playerMaxPosition}).`);
+ }
}
};
exports.checkUniqueNameInPlayers = players => {
- const playerSet = [...new Set(players.map(player => player.name))];
- if (playerSet.length !== players.length) {
+ const playerNameSet = [...new Set(players.map(({ name }) => name))];
+ if (playerNameSet.length !== players.length) {
throw generateError("PLAYERS_NAME_NOT_UNIQUE", "Players don't all have unique name.");
}
};
@@ -129,11 +155,12 @@ exports.checkUniqueNameInPlayers = players => {
exports.checkAndFillDataBeforeCreate = async data => {
await this.checkUserCurrentGames(data.gameMaster);
this.checkUniqueNameInPlayers(data.players);
+ this.checkPlayersPosition(data.players);
this.fillPlayersData(data.players);
this.checkRolesCompatibility(data.players);
+ this.fillOptionsData(data);
this.checkAdditionalCardsData(data);
this.fillTickData(data);
- this.fillOptionsData(data);
data.waiting = await this.getWaitingQueueWithNightActions(data);
};
@@ -387,8 +414,7 @@ exports.refreshNightWaitingQueue = async game => {
"gameId": game._id, "turn": game.turn, "phase": "night",
"play.source.name": waiting.for, "play.action": waiting.to,
};
- if (currentPlay.for !== waiting.for && currentPlay.to !== waiting.to &&
- !await GameHistory.findOne(gameHistorySearch)) {
+ if (currentPlay.for !== waiting.for && currentPlay.to !== waiting.to && !await GameHistory.findOne(gameHistorySearch)) {
newWaitingQueue.push(waiting);
}
}
@@ -427,6 +453,9 @@ exports.fillWaitingQueueWithDayActions = async(game, gameHistoryEntry) => {
}
}
}
+ if (await this.isTimeToElectSheriff(game)) {
+ game.waiting.push({ for: "all", to: "elect-sheriff" });
+ }
};
exports.isGroupCallableDuringTheNight = (game, group) => {
@@ -435,16 +464,19 @@ exports.isGroupCallableDuringTheNight = (game, group) => {
return !!cupidPlayer && !doesPlayerHaveAttribute(cupidPlayer, "powerless");
} else if (group === "charmed") {
const piedPiperPlayer = getPlayerWithRole("pied-piper", game);
- return piedPiperPlayer?.isAlive && piedPiperPlayer.side.current !== "werewolves" && !doesPlayerHaveAttribute(piedPiperPlayer, "powerless");
+ return piedPiperPlayer?.isAlive && (piedPiperPlayer.side.current === "villagers" || !game.options.roles.piedPiper.isPowerlessIfInfected) &&
+ !doesPlayerHaveAttribute(piedPiperPlayer, "powerless");
}
const players = getPlayersWithSide(group, game);
return game.tick === 1 ? !!players.length : !!players.length && players.some(({ isAlive }) => isAlive);
};
exports.isWhiteWerewolfCallableDuringTheNight = async game => {
+ const { wakingUpInterval: whiteWerewolfWakingUpInterval } = game.options.roles.whiteWerewolf;
const whiteWerewolfPlayer = getPlayerWithRole("white-werewolf", game);
const lastWhiteWerewolfPlay = await GameHistory.getLastWhiteWerewolfPlay(game._id);
- return whiteWerewolfPlayer?.isAlive && (!lastWhiteWerewolfPlay || game.turn - lastWhiteWerewolfPlay.turn > 1);
+ const turnsSinceLastWhiteWerewolfPlay = lastWhiteWerewolfPlay ? game.turn - lastWhiteWerewolfPlay.turn : undefined;
+ return whiteWerewolfPlayer?.isAlive && (!lastWhiteWerewolfPlay || turnsSinceLastWhiteWerewolfPlay >= whiteWerewolfWakingUpInterval);
};
exports.areThreeBrothersCallableDuringTheNight = async game => {
@@ -475,13 +507,13 @@ exports.isRoleCallableDuringTheNight = (game, role) => {
} else if (role === "three-brothers") {
return this.areThreeBrothersCallableDuringTheNight(game);
} else if (role === "big-bad-wolf") {
- return player.isAlive && areAllWerewolvesAlive(game);
+ return player.isAlive && (!game.options.roles.bigBadWolf.isPowerlessIfWerewolfDies || areAllWerewolvesAlive(game));
} else if (role === "pied-piper") {
- return player.isAlive && player.side.current === "villagers";
+ return player.isAlive && (player.side.current === "villagers" || !game.options.roles.piedPiper.isPowerlessIfInfected);
} else if (role === "white-werewolf") {
return this.isWhiteWerewolfCallableDuringTheNight(game);
}
- return game.tick === 1 ? !!player : !!player && player.isAlive;
+ return !!player && player.isAlive;
};
exports.isSheriffCallableDuringTheNight = game => {
@@ -492,9 +524,7 @@ exports.isSheriffCallableDuringTheNight = game => {
exports.isSourceCallableDuringTheNight = (game, source, action) => {
if (source === "all") {
- if (action === "elect-sheriff") {
- return getProp(game, "options.roles.sheriff.isEnabled", true);
- } else if (action === "vote") {
+ if (action === "vote") {
return !!getPlayerWithRole("angel", game);
}
} else if (source === "sheriff") {
@@ -504,6 +534,15 @@ exports.isSourceCallableDuringTheNight = (game, source, action) => {
return sourceType === "group" ? this.isGroupCallableDuringTheNight(game, source) : this.isRoleCallableDuringTheNight(game, source);
};
+exports.isTimeToElectSheriff = async game => {
+ const sheriffOptions = game.options.roles.sheriff;
+ if (sheriffOptions.isEnabled && game.turn === sheriffOptions.electedAt.turn && game.phase === sheriffOptions.electedAt.phase) {
+ const allElectSheriffPlays = await GameHistory.find({ "gameId": game._id, "play.source.name": "all", "play.action": "elect-sheriff" });
+ return !allElectSheriffPlays.length;
+ }
+ return false;
+};
+
exports.getWaitingQueueWithNightActions = async game => {
let actionsOrder;
if (game.turn === 1 && game.phase === "night") {
@@ -512,6 +551,9 @@ exports.getWaitingQueueWithNightActions = async game => {
actionsOrder = getGameTurnNightActionsOrder().filter(action => !action.isFirstNightOnly);
}
const waitingQueue = [];
+ if (await this.isTimeToElectSheriff(game)) {
+ waitingQueue.push({ for: "all", to: "elect-sheriff" });
+ }
for (const { source, action } of actionsOrder) {
if (await this.isSourceCallableDuringTheNight(game, source, action)) {
waitingQueue.push({ for: source, to: action });
@@ -528,12 +570,14 @@ exports.fillWaitingQueue = async(game, gameHistoryEntry) => {
game.waiting.push({ for: "all", to: "vote" });
}
this.decreasePlayersAttributesRemainingPhases(game);
+ Player.makeBearTamerGrowls(game);
if (!game.waiting.length) {
await this.fillWaitingQueue(game, gameHistoryEntry);
}
} else if (game.phase === "day") {
await this.fillWaitingQueueWithDayActions(game, gameHistoryEntry);
if (!game.waiting || !game.waiting.length) {
+ await Player.makeWerewolfDiesFromDisease(game, gameHistoryEntry);
this.decreasePlayersAttributesRemainingPhases(game);
game.phase = "night";
game.turn++;
@@ -564,6 +608,7 @@ exports.generatePlayMethods = () => ({
"white-werewolf": Player.whiteWerewolfPlays,
"stuttering-judge": () => undefined,
"thief": Player.thiefPlays,
+ "fox": Player.foxPlays,
});
exports.generateGameHistoryEntry = (game, { source, ...rest }) => ({
diff --git a/src/controllers/GameHistory.js b/src/controllers/GameHistory.js
index f38ec6c..8685216 100755
--- a/src/controllers/GameHistory.js
+++ b/src/controllers/GameHistory.js
@@ -75,7 +75,10 @@ exports.isInfectionUsed = async gameId => !!await this.findOne({ gameId, "play.t
exports.didJudgeChooseSign = async gameId => !!await this.findOne({ gameId, "play.action": "choose-sign", "play.source.name": "stuttering-judge" });
-exports.isSecondVoteRequestUsed = async gameId => !!await this.findOne({ gameId, "play.doesJudgeRequestAnotherVote": true });
+exports.doesStutteringJudgeHaveVoteRequestsLeft = async game => {
+ const stutteringJudgeVoteRequests = await this.find({ "gameId": game._id, "play.doesJudgeRequestAnotherVote": true });
+ return stutteringJudgeVoteRequests.length < game.options.roles.stutteringJudge.voteRequestsCount;
+};
exports.getLastNightPlay = gameId => {
const nightPlayActions = [...turnPreNightActionsOrder, ...turnNightActionsOrder].map(({ action }) => action);
diff --git a/src/controllers/Player.js b/src/controllers/Player.js
index bc2abc2..84b8d3e 100644
--- a/src/controllers/Player.js
+++ b/src/controllers/Player.js
@@ -7,7 +7,7 @@ const {
} = require("../helpers/functions/Player");
const {
getPlayerWithAttribute, getPlayerWithRole, getPlayerWithId, filterOutSourcesFromWaitingQueue,
- getRemainingPlayersToCharm, getRemainingVillagersToEat, getRemainingWerewolvesToEat,
+ getRemainingPlayersToCharm, getRemainingVillagersToEat, getRemainingWerewolvesToEat, getNearestNeighbor,
} = require("../helpers/functions/Game");
const { getVillagerRoles, getWerewolfRoles, getRoles } = require("../helpers/functions/Role");
const { generateError } = require("../helpers/functions/Error");
@@ -39,6 +39,13 @@ exports.checkPiedPiperTargets = target => {
}
};
+exports.checkProtectTarget = async(target, game) => {
+ const lastProtectedTarget = await GameHistory.getLastProtectedPlayer(game._id);
+ if (lastProtectedTarget && lastProtectedTarget._id.toString() === target.player._id.toString() && !game.options.roles.guard.canProtectTwice) {
+ throw generateError("CANT_PROTECT_TWICE", `Guard can't protect the same player twice in a row.`);
+ }
+};
+
exports.checkEatTarget = async(target, game, source) => {
if (source !== "white-werewolf" && target.player.side.current === "werewolves") {
throw generateError("CANT_EAT_EACH_OTHER", `Werewolves target can't be a player with current side "werewolves".`);
@@ -71,10 +78,7 @@ exports.checkTargetDependingOnPlay = async(target, game, { source, action }) =>
throw generateError("BAD_LIFE_POTION_USE", `Witch can only use life potion on a target eaten by "werewolves" of "big-bad-wolf".`);
}
} else if (action === "protect") {
- const lastProtectedTarget = await GameHistory.getLastProtectedPlayer(game._id);
- if (lastProtectedTarget && lastProtectedTarget._id.toString() === target.player._id.toString()) {
- throw generateError("CANT_PROTECT_TWICE", `Guard can't protect the same player twice in a row.`);
- }
+ await this.checkProtectTarget(target, game);
} else if (action === "settle-votes") {
const lastVotePlay = await GameHistory.getLastVotePlay(game._id);
if (lastVotePlay && !lastVotePlay.play.targets.find(({ player }) => player._id.toString() === target.player._id.toString())) {
@@ -99,6 +103,17 @@ exports.checkAndFillPlayerTarget = (target, game) => {
target.player = player;
};
+exports.addFoxTargets = (targets, game) => {
+ const leftAliveNeighbor = getNearestNeighbor(targets[0].player, game.players, "left", { isAlive: true });
+ const rightAliveNeighbor = getNearestNeighbor(targets[0].player, game.players, "right", { isAlive: true });
+ if (leftAliveNeighbor) {
+ targets.unshift({ player: leftAliveNeighbor._id });
+ }
+ if (rightAliveNeighbor && leftAliveNeighbor !== rightAliveNeighbor) {
+ targets.push({ player: rightAliveNeighbor._id });
+ }
+};
+
exports.checkTargetStructure = (target, action) => {
if (target.player === undefined) {
throw generateError("BAD_TARGET_STRUCTURE", `Bad target structure. Field "player" is missing.`);
@@ -134,10 +149,15 @@ exports.checkAndFillTargets = async(targets, game, options) => {
if (!targets || !targets.length) {
return;
}
- for (let i = 0; i < targets.length; i++) {
- this.checkTargetStructure(targets[i], options.play.action);
- this.checkAndFillPlayerTarget(targets[i], game);
- await this.checkTargetDependingOnPlay(targets[i], game, options.play);
+ for (const target of targets) {
+ this.checkTargetStructure(target, options.play.action);
+ }
+ if (options.play.action === "sniff") {
+ this.addFoxTargets(targets, game);
+ }
+ for (const target of targets) {
+ this.checkAndFillPlayerTarget(target, game);
+ await this.checkTargetDependingOnPlay(target, game, options.play);
}
this.checkUniqueTargets(targets);
await this.checkAllTargetsDependingOnAction(targets, game, options.play.action);
@@ -205,7 +225,7 @@ exports.applyConsequencesDependingOnKilledPlayerRole = async(player, action, gam
if (player.role.current === "hunter" && !doesPlayerHaveAttribute(player, "powerless")) {
this.insertActionImmediately(game, { for: "hunter", to: "shoot" });
} else if (player.role.current === "ancient") {
- if (ancientRevengeActions.includes(action)) {
+ if (ancientRevengeActions.includes(action) && game.options.roles.ancient.doesTakeHisRevenge) {
for (const { _id, isAlive, side } of game.players) {
if (isAlive && side.original === "villagers") {
this.addPlayerAttribute(_id, "powerless", game);
@@ -218,8 +238,14 @@ exports.applyConsequencesDependingOnKilledPlayerRole = async(player, action, gam
if (idiotPlayer?.isAlive && idiotPlayer.role.isRevealed && game.options.roles.idiot.doesDieOnAncientDeath) {
await this.killPlayer(idiotPlayer._id, "reconsider", game, gameHistoryEntry);
}
- } else if (player.role.current === "scapegoat" && action === "vote" && options?.nominatedPlayers?.length > 1) {
+ } else if (player.role.current === "scapegoat" && action === "vote" && options?.nominatedPlayers?.length > 1 &&
+ !doesPlayerHaveAttribute(player, "powerless")) {
this.insertActionImmediately(game, { for: "scapegoat", to: "ban-voting" });
+ } else if (player.role.current === "rusty-sword-knight" && action === "eat" && !doesPlayerHaveAttribute(player, "powerless")) {
+ const leftAliveWerewolfNeighbor = getNearestNeighbor(player._id, game.players, "left", { isAlive: true, side: "werewolves" });
+ if (leftAliveWerewolfNeighbor) {
+ this.addPlayerAttribute(leftAliveWerewolfNeighbor._id, "contaminated", game);
+ }
}
};
@@ -234,7 +260,7 @@ exports.fillMurderedData = (player, action, gameHistoryEntry, options) => {
}
};
-exports.isAncientKillable = async(action, gameHistoryEntry) => {
+exports.isAncientKillable = async(action, game, gameHistoryEntry) => {
if (action !== "eat") {
return true;
}
@@ -254,7 +280,7 @@ exports.isAncientKillable = async(action, gameHistoryEntry) => {
"play.source.name": "guard",
"play.targets": { $elemMatch: { "player.role.current": "ancient" } },
};
- let livesCount = 2;
+ let livesCount = game.options.roles.ancient.livesCountAgainstWerewolves;
for (const werewolvesPlay of werewolvesPlaysOnAncient) {
if (werewolvesPlay.play.action === "eat" && werewolvesPlay.play.targets.find(({ player }) => player.role.current === "ancient") &&
!await GameHistory.findOne({ ...ancientSavedByWitchPlaySearch, turn: werewolvesPlay.turn }) &&
@@ -265,15 +291,15 @@ exports.isAncientKillable = async(action, gameHistoryEntry) => {
return livesCount <= 0;
};
-exports.isPlayerKillable = async({ role, attributes }, action, alreadyRevealed, gameHistoryEntry) => role.current !== "ancient" &&
- role.current !== "idiot" || role.current === "ancient" && await this.isAncientKillable(action, gameHistoryEntry) ||
+exports.isPlayerKillable = async({ role, attributes }, action, alreadyRevealed, game, gameHistoryEntry) => role.current !== "ancient" &&
+ role.current !== "idiot" || role.current === "ancient" && await this.isAncientKillable(action, game, gameHistoryEntry) ||
role.current === "idiot" && isIdiotKillable(action, { attributes }, alreadyRevealed);
exports.killPlayer = async(playerId, action, game, gameHistoryEntry, options = {}) => {
const player = getPlayerWithId(playerId, game);
if (player?.isAlive && (action !== "eat" || canBeEaten(player, game))) {
const alreadyRevealed = player.role.isRevealed;
- if (!alreadyRevealed && (player.role.current !== "ancient" || await this.isAncientKillable(action, gameHistoryEntry))) {
+ if (!alreadyRevealed && (player.role.current !== "ancient" || await this.isAncientKillable(action, game, gameHistoryEntry))) {
player.role.isRevealed = true;
this.insertRevealedPlayerIntoGameHistoryEntry(player, gameHistoryEntry);
if (player.role.current === "idiot" && !doesPlayerHaveAttribute(player, "powerless") &&
@@ -281,7 +307,7 @@ exports.killPlayer = async(playerId, action, game, gameHistoryEntry, options = {
this.addPlayerAttribute(player._id, "cant-vote", game, { source: "all" });
}
}
- if (await this.isPlayerKillable(player, action, alreadyRevealed, gameHistoryEntry)) {
+ if (await this.isPlayerKillable(player, action, alreadyRevealed, game, gameHistoryEntry)) {
player.isAlive = false;
this.fillMurderedData(player, action, gameHistoryEntry, options);
if (action === "vote") {
@@ -423,8 +449,8 @@ exports.checkJudgeSecondVoteRequest = async game => {
throw generateError("STUTTERING_JUDGE_POWERLESS", "Stuttering judge is powerless and so can't request another vote.");
} else if (!await GameHistory.didJudgeChooseSign(game._id)) {
throw generateError("STUTTERING_JUDGE_DIDNT_CHOOSE_SIGN_YET", `Stuttering judge didn't choose his sign yet and so can't request another vote.`);
- } else if (await GameHistory.isSecondVoteRequestUsed(game._id)) {
- throw generateError("ONLY_ONE_SECOND_VOTE_REQUEST", "Second vote request has been already made.");
+ } else if (!await GameHistory.doesStutteringJudgeHaveVoteRequestsLeft(game)) {
+ throw generateError("VOTE_REQUESTS_EXCEEDED", "Stuttering judge doesn't have any vote request left.");
}
};
@@ -444,13 +470,24 @@ exports.checkAndFillVotes = async(votes, game, options) => {
}
};
+exports.foxPlays = async(play, game) => {
+ const { targets } = play;
+ await this.checkAndFillTargets(targets, game, { canBeUnset: true, canBeEmpty: true, expectedLength: 1, play });
+ if (targets?.length && !targets.find(({ player }) => player.side.current === "werewolves") &&
+ game.options.roles.fox.isPowerlessIfMissesWerewolf) {
+ const foxPlayer = getPlayerWithRole("fox", game);
+ this.addPlayerAttribute(foxPlayer._id, "powerless", game, { source: "fox" });
+ }
+};
+
exports.checkAndGetChosenCard = (chosenCardId, game) => {
const chosenCard = chosenCardId ? game.additionalCards.find(({ _id }) => _id.toString() === chosenCardId.toString()) : null;
const werewolvesRoles = getWerewolfRoles();
const thiefAdditionalCards = game.additionalCards.filter(({ for: recipient }) => recipient === "thief");
if (chosenCardId && !chosenCard) {
throw generateError("CHOSEN_CARD_NOT_FOUND", `The chosen card with id "${chosenCardId}" is not found in additional cards.`);
- } else if (!chosenCard && thiefAdditionalCards.every(({ role: roleName }) => werewolvesRoles.find(({ name }) => name === roleName))) {
+ } else if (!chosenCard && thiefAdditionalCards.every(({ role: roleName }) => werewolvesRoles.find(({ name }) => name === roleName)) &&
+ game.options.roles.thief.mustChooseBetweenWerewolves) {
throw generateError("THIEF_MUST_STEAL", `As all additional cards for thief are on the werewolves side, he must choose one of them.`);
}
if (chosenCard) {
@@ -482,7 +519,9 @@ exports.whiteWerewolfPlays = async(play, game) => {
exports.piedPiperPlays = async(play, game) => {
const { targets } = play;
- const targetsExpectedLength = getRemainingPlayersToCharm(game).length === 1 ? 1 : 2;
+ const { charmedPeopleCountPerNight: maxCharmedPeople } = game.options.roles.piedPiper;
+ const remainingPlayersToCharmCount = getRemainingPlayersToCharm(game).length;
+ const targetsExpectedLength = remainingPlayersToCharmCount >= maxCharmedPeople ? maxCharmedPeople : remainingPlayersToCharmCount;
await this.checkAndFillTargets(targets, game, { expectedLength: targetsExpectedLength, play });
for (const { player } of targets) {
this.addPlayerAttribute(player._id, "charmed", game);
@@ -558,11 +597,11 @@ exports.werewolvesPlay = async(play, game, gameHistoryEntry) => {
if (targets[0].isInfected) {
const infectedPlayer = getPlayerWithId(targets[0].player._id, game);
if (infectedPlayer) {
- if (infectedPlayer.role.current === "ancient" && !await this.isAncientKillable(play.action, gameHistoryEntry)) {
+ if (infectedPlayer.role.current === "ancient" && !await this.isAncientKillable(play.action, game, gameHistoryEntry)) {
this.addPlayerAttribute(targets[0].player._id, "eaten", game);
} else {
infectedPlayer.side.current = "werewolves";
- if (infectedPlayer.role.current === "pied-piper") {
+ if (infectedPlayer.role.current === "pied-piper" && game.options.roles.piedPiper.isPowerlessIfInfected) {
filterOutSourcesFromWaitingQueue(game, ["pied-piper", "charmed"]);
}
}
@@ -672,4 +711,23 @@ exports.drankDeathPotion = async(game, play, gameHistoryEntry) => {
const poisonedPlayer = getPlayerWithAttribute("drank-death-potion", game);
await this.killPlayer(poisonedPlayer._id, "use-potion", game, gameHistoryEntry);
this.removePlayerAttribute(poisonedPlayer._id, "drank-death-potion", game);
+};
+
+exports.makeBearTamerGrowls = game => {
+ const bearTamerPlayer = getPlayerWithRole("bear-tamer", game);
+ if (bearTamerPlayer && !doesPlayerHaveAttribute(bearTamerPlayer, "powerless")) {
+ const leftAliveNeighbor = getNearestNeighbor(bearTamerPlayer._id, game.players, "left", { isAlive: true });
+ const rightAliveNeighbor = getNearestNeighbor(bearTamerPlayer._id, game.players, "right", { isAlive: true });
+ if (bearTamerPlayer.side.current === "werewolves" && game.options.roles.bearTamer.doesGrowlIfInfected ||
+ leftAliveNeighbor?.side.current === "werewolves" || rightAliveNeighbor?.side.current === "werewolves") {
+ this.addPlayerAttribute(bearTamerPlayer._id, "growls", game);
+ }
+ }
+};
+
+exports.makeWerewolfDiesFromDisease = async(game, gameHistoryEntry) => {
+ const contaminatedWerewolf = getPlayerWithAttribute("contaminated", game);
+ if (contaminatedWerewolf) {
+ await this.killPlayer(contaminatedWerewolf._id, "disease", game, gameHistoryEntry);
+ }
};
\ No newline at end of file
diff --git a/src/controllers/User.js b/src/controllers/User.js
index ac013fc..87bf304 100755
--- a/src/controllers/User.js
+++ b/src/controllers/User.js
@@ -1,3 +1,4 @@
+const axios = require("axios");
const { flatten } = require("mongo-dot-notation");
const { sign } = require("jsonwebtoken");
const passport = require("passport");
@@ -8,7 +9,24 @@ const { checkJWTUserRights } = require("../helpers/functions/User");
const { checkRequestData } = require("../helpers/functions/Express");
const Config = require("../../config");
+exports.checkDataBeforeCreate = async data => {
+ const existingUser = await this.findOne({ email: data.email });
+ if (existingUser) {
+ if (existingUser.registration.method === data.registration.method) {
+ throw generateError("EMAIL_EXISTS", "The email provided already exists.");
+ }
+ if (existingUser.registration.method === "local") {
+ throw generateError("EMAIL_EXISTS_WITH_LOCAL_REGISTRATION", "The email provided already exists with local registration.");
+ } else if (existingUser.registration.method === "facebook") {
+ throw generateError("EMAIL_EXISTS_WITH_FACEBOOK_REGISTRATION", "The email provided already exists with facebook registration.");
+ } else if (existingUser.registration.method === "google") {
+ throw generateError("EMAIL_EXISTS_WITH_GOOGLE_REGISTRATION", "The email provided already exists with google registration.");
+ }
+ }
+};
+
exports.create = async(data, options = {}) => {
+ await this.checkDataBeforeCreate(data);
const { toJSON } = options;
delete options.toJSON;
if (!Array.isArray(data)) {
@@ -53,6 +71,7 @@ exports.postUser = async(req, res) => {
try {
const { body } = checkRequestData(req);
await this.generateSaltAndHash(body);
+ body.registration = { method: "local" };
const newUser = await this.create(body, { toJSON: true });
delete newUser.password;
res.status(200).json(newUser);
@@ -90,6 +109,8 @@ exports.getUser = async(req, res) => {
}
};
+exports.getJWT = user => sign({ userId: user._id }, Config.app.JWTSecret);
+
exports.login = (req, res) => {
try {
checkRequestData(req);
@@ -101,11 +122,71 @@ exports.login = (req, res) => {
if (loginErr) {
res.status(500).send(loginErr);
}
- const token = sign({ userId: user._id, exp: Math.floor(Date.now() / 1000) + 3600 * 24 }, Config.app.JWTSecret);
+ const token = this.getJWT(user);
return res.status(200).json({ token });
});
})(req, res);
} catch (e) {
sendError(res, e);
}
+};
+
+exports.getFacebookUser = async accessToken => {
+ try {
+ const { data: facebookApp } = await axios.get(`https://graph.facebook.com/app?access_token=${accessToken}`);
+ if (facebookApp.id !== Config.facebook.app.ID) {
+ throw generateError("BAD_FACEBOOK_ACCESS_TOKEN", `Access token "${accessToken}" doesn't belong to the Werewolves Assistant Facebook app.`);
+ }
+ const { data: facebookUser } = await axios.get(`https://graph.facebook.com/me?fields=email&access_token=${accessToken}`);
+ return facebookUser;
+ } catch (e) {
+ throw generateError("BAD_FACEBOOK_ACCESS_TOKEN", `Access token "${accessToken}" doesn't allow to get user info.`);
+ }
+};
+
+exports.loginWithFacebook = async(req, res) => {
+ try {
+ const { body } = checkRequestData(req);
+ const facebookUser = await this.getFacebookUser(body.accessToken);
+ if (!facebookUser.email) {
+ throw generateError("NEED_FACEBOOK_EMAIL_PERMISSION", `You need to share your email to login with Facebook.`);
+ }
+ const facebookUserData = { email: facebookUser.email, registration: { method: "facebook" } };
+ let user = await this.findOne(facebookUserData);
+ if (!user) {
+ user = await this.create(facebookUserData);
+ }
+ const token = this.getJWT(user);
+ res.status(200).json({ token });
+ } catch (e) {
+ sendError(res, e);
+ }
+};
+
+exports.getGoogleUser = async idToken => {
+ try {
+ const { data } = await axios.get(`https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=${idToken}`);
+ if (data.azp !== Config.google.client.ID) {
+ throw generateError("BAD_GOOGLE_ID_TOKEN", `Id token "${idToken}" doesn't belong to the Werewolves Assistant Google app.`);
+ }
+ return data;
+ } catch (e) {
+ throw generateError("BAD_GOOGLE_ID_TOKEN", `Id token "${idToken}" doesn't allow to get user info.`);
+ }
+};
+
+exports.loginWithGoogle = async(req, res) => {
+ try {
+ const { body } = checkRequestData(req);
+ const googleUser = await this.getGoogleUser(body.idToken);
+ const googleUserData = { email: googleUser.email, registration: { method: "google" } };
+ let user = await this.findOne(googleUserData);
+ if (!user) {
+ user = await this.create(googleUserData);
+ }
+ const token = this.getJWT(user);
+ res.status(200).json({ token });
+ } catch (e) {
+ sendError(res, e);
+ }
};
\ No newline at end of file
diff --git a/src/db/schemas/Game.js b/src/db/schemas/Game.js
index 21add4a..8b83497 100755
--- a/src/db/schemas/Game.js
+++ b/src/db/schemas/Game.js
@@ -8,22 +8,61 @@ const {
const { getPlayerActions } = require("../../helpers/functions/Player");
const gameOptions = {
+ repartition: {
+ isHidden: {
+ type: Boolean,
+ default: false,
+ },
+ },
roles: {
+ areRevealedOnDeath: {
+ type: Boolean,
+ default: true,
+ },
sheriff: {
isEnabled: {
type: Boolean,
default: true,
},
+ electedAt: {
+ turn: {
+ type: Number,
+ default: 1,
+ },
+ phase: {
+ type: String,
+ enum: getGamePhases(),
+ default: "night",
+ },
+ },
hasDoubledVote: {
type: Boolean,
default: true,
},
},
+ bigBadWolf: {
+ isPowerlessIfWerewolfDies: {
+ type: Boolean,
+ default: true,
+ },
+ },
+ whiteWerewolf: {
+ wakingUpInterval: {
+ type: Number,
+ default: 2,
+ min: 1,
+ max: 5,
+ },
+ },
seer: {
isTalkative: {
type: Boolean,
default: true,
},
+ canSeeRoles: {
+ type: Boolean,
+ default: true,
+ },
},
littleGirl: {
isProtectedByGuard: {
@@ -31,6 +70,24 @@ const gameOptions = {
default: false,
},
},
+ guard: {
+ canProtectTwice: {
+ type: Boolean,
+ default: false,
+ },
+ },
+ ancient: {
+ livesCountAgainstWerewolves: {
+ type: Number,
+ default: 2,
+ min: 1,
+ max: 5,
+ },
+ doesTakeHisRevenge: {
+ type: Boolean,
+ default: true,
+ },
+ },
idiot: {
doesDieOnAncientDeath: {
type: Boolean,
@@ -53,6 +110,62 @@ const gameOptions = {
max: 5,
},
},
+ fox: {
+ isPowerlessIfMissesWerewolf: {
+ type: Boolean,
+ default: true,
+ },
+ },
+ bearTamer: {
+ doesGrowlIfInfected: {
+ type: Boolean,
+ default: true,
+ },
+ },
+ stutteringJudge: {
+ voteRequestsCount: {
+ type: Number,
+ default: 1,
+ min: 1,
+ max: 5,
+ },
+ },
+ wildChild: {
+ isTransformationRevealed: {
+ type: Boolean,
+ default: false,
+ },
+ },
+ dogWolf: {
+ isChosenSideRevealed: {
+ type: Boolean,
+ default: false,
+ },
+ },
+ thief: {
+ mustChooseBetweenWerewolves: {
+ type: Boolean,
+ default: true,
+ },
+ additionalCardsCount: {
+ type: Number,
+ default: 2,
+ min: 1,
+ max: 5,
+ },
+ },
+ piedPiper: {
+ charmedPeopleCountPerNight: {
+ type: Number,
+ default: 2,
+ min: 1,
+ max: 5,
+ },
+ isPowerlessIfInfected: {
+ type: Boolean,
+ default: true,
+ },
+ },
raven: {
markPenalty: {
type: Number,
diff --git a/src/db/schemas/Player.js b/src/db/schemas/Player.js
index 1677e88..2178f60 100755
--- a/src/db/schemas/Player.js
+++ b/src/db/schemas/Player.js
@@ -31,21 +31,6 @@ const PlayerAttributeSchema = new Schema({
versionKey: false,
});
-const PlayerPowerSchema = new Schema({
- action: {
- type: String,
- required: true,
- },
- used: {
- type: Boolean,
- required: true,
- },
-}, {
- _id: false,
- timestamps: false,
- versionKey: false,
-});
-
const MurderedSchema = new Schema({
by: {
type: String,
@@ -100,9 +85,9 @@ const PlayerSchema = new Schema({
type: [PlayerAttributeSchema],
default: undefined,
},
- powers: {
- type: [PlayerPowerSchema],
- default: undefined,
+ position: {
+ type: Number,
+ min: 0,
},
isAlive: {
type: Boolean,
diff --git a/src/db/schemas/User.js b/src/db/schemas/User.js
index e1d7d56..6ae65e1 100755
--- a/src/db/schemas/User.js
+++ b/src/db/schemas/User.js
@@ -1,4 +1,5 @@
const { Schema } = require("mongoose");
+const { getRegistrationMethods } = require("../../helpers/functions/User");
const userSchema = new Schema({
email: {
@@ -6,9 +7,13 @@ const userSchema = new Schema({
required: true,
unique: true,
},
- password: {
- type: String,
- required: true,
+ password: { type: String },
+ registration: {
+ method: {
+ type: String,
+ enum: getRegistrationMethods(),
+ default: "local",
+ },
},
}, {
timestamps: true,
diff --git a/src/helpers/constants/Error.js b/src/helpers/constants/Error.js
index 0e4f72c..db2261c 100644
--- a/src/helpers/constants/Error.js
+++ b/src/helpers/constants/Error.js
@@ -211,7 +211,7 @@ exports.errorMetadata = {
code: 53,
HTTPCode: 400,
},
- ONLY_ONE_SECOND_VOTE_REQUEST: {
+ VOTE_REQUESTS_EXCEEDED: {
code: 54,
HTTPCode: 400,
},
@@ -259,4 +259,44 @@ exports.errorMetadata = {
code: 65,
HTTPCode: 400,
},
+ ALL_PLAYERS_POSITION_NOT_SET: {
+ code: 66,
+ HTTPCode: 400,
+ },
+ PLAYERS_POSITION_NOT_UNIQUE: {
+ code: 67,
+ HTTPCode: 400,
+ },
+ PLAYER_POSITION_TOO_HIGH: {
+ code: 68,
+ HTTPCode: 400,
+ },
+ THIEF_ADDITIONAL_CARDS_COUNT_NOT_RESPECTED: {
+ code: 69,
+ HTTPCode: 400,
+ },
+ BAD_FACEBOOK_ACCESS_TOKEN: {
+ code: 70,
+ HTTPCode: 400,
+ },
+ NEED_FACEBOOK_EMAIL_PERMISSION: {
+ code: 71,
+ HTTPCode: 400,
+ },
+ EMAIL_EXISTS_WITH_LOCAL_REGISTRATION: {
+ code: 72,
+ HTTPCode: 400,
+ },
+ EMAIL_EXISTS_WITH_FACEBOOK_REGISTRATION: {
+ code: 73,
+ HTTPCode: 400,
+ },
+ EMAIL_EXISTS_WITH_GOOGLE_REGISTRATION: {
+ code: 74,
+ HTTPCode: 400,
+ },
+ BAD_GOOGLE_ID_TOKEN: {
+ code: 75,
+ HTTPCode: 400,
+ },
};
\ No newline at end of file
diff --git a/src/helpers/constants/Game.js b/src/helpers/constants/Game.js
index c4658b4..7b93286 100644
--- a/src/helpers/constants/Game.js
+++ b/src/helpers/constants/Game.js
@@ -20,14 +20,14 @@ exports.populate = [
];
exports.turnNightActionsOrder = [
- { source: "all", action: "elect-sheriff", isFirstNightOnly: true },
{ source: "all", action: "vote", isFirstNightOnly: true },
{ source: "thief", action: "choose-card", isFirstNightOnly: true },
{ source: "dog-wolf", action: "choose-side", isFirstNightOnly: true },
{ source: "cupid", action: "charm", isFirstNightOnly: true },
+ { source: "seer", action: "look" },
+ { source: "fox", action: "sniff" },
{ source: "lovers", action: "meet-each-other", isFirstNightOnly: true },
{ source: "stuttering-judge", action: "choose-sign", isFirstNightOnly: true },
- { source: "seer", action: "look" },
{ source: "two-sisters", action: "meet-each-other" },
{ source: "three-brothers", action: "meet-each-other" },
{ source: "wild-child", action: "choose-model", isFirstNightOnly: true },
@@ -44,13 +44,30 @@ exports.turnNightActionsOrder = [
exports.findFields = ["status"];
exports.defaultGameOptions = {
+ repartition: { isHidden: false },
roles: {
- sheriff: { isEnabled: true, hasDoubledVote: true },
- seer: { isTalkative: true },
+ areRevealedOnDeath: true,
+ sheriff: {
+ isEnabled: true,
+ electedAt: { turn: 1, phase: "night" },
+ hasDoubledVote: true,
+ },
+ bigBadWolf: { isPowerlessIfWerewolfDies: true },
+ whiteWerewolf: { wakingUpInterval: 2 },
+ seer: { isTalkative: true, canSeeRoles: true },
littleGirl: { isProtectedByGuard: false },
+ guard: { canProtectTwice: false },
+ ancient: { livesCountAgainstWerewolves: 2, doesTakeHisRevenge: true },
idiot: { doesDieOnAncientDeath: true },
twoSisters: { wakingUpInterval: 2 },
threeBrothers: { wakingUpInterval: 2 },
+ fox: { isPowerlessIfMissesWerewolf: true },
+ bearTamer: { doesGrowlIfInfected: true },
+ stutteringJudge: { voteRequestsCount: 1 },
+ wildChild: { isTransformationRevealed: false },
+ dogWolf: { isChosenSideRevealed: false },
+ thief: { mustChooseBetweenWerewolves: true, additionalCardsCount: 2 },
+ piedPiper: { charmedPeopleCountPerNight: 2, isPowerlessIfInfected: true },
raven: { markPenalty: 2 },
},
};
diff --git a/src/helpers/constants/Player.js b/src/helpers/constants/Player.js
index 7bb9713..3801d3a 100644
--- a/src/helpers/constants/Player.js
+++ b/src/helpers/constants/Player.js
@@ -12,9 +12,12 @@ exports.playerAttributes = [
{ name: "in-love", source: "cupid" },
{ name: "worshiped", source: "wild-child" },
{ name: "powerless", source: "ancient" },
+ { name: "powerless", source: "fox" },
{ name: "cant-vote", source: "scapegoat", remainingPhases: 2 },
{ name: "cant-vote", source: "all" },
{ name: "charmed", source: "pied-piper" },
+ { name: "growls", source: "bear-tamer", remainingPhases: 1 },
+ { name: "contaminated", source: "rusty-sword-knight", remainingPhases: 2 },
];
exports.playerActions = [
@@ -35,6 +38,7 @@ exports.playerActions = [
"ban-voting",
"choose-sign",
"choose-card",
+ "sniff",
];
exports.murderedPossibilities = [
@@ -47,4 +51,5 @@ exports.murderedPossibilities = [
{ by: "all", of: "vote" },
{ by: "cupid", of: "charm" },
{ by: "all", of: "reconsider" },
+ { by: "rusty-sword-knight", of: "disease" },
];
\ No newline at end of file
diff --git a/src/helpers/constants/Role.js b/src/helpers/constants/Role.js
index 70a6f13..e6b586e 100644
--- a/src/helpers/constants/Role.js
+++ b/src/helpers/constants/Role.js
@@ -3,30 +3,33 @@ exports.sideNames = ["villagers", "werewolves"];
exports.groupNames = [...this.sideNames, "lovers", "charmed"];
exports.roles = [
- { name: "werewolf", side: "werewolves", maxInGame: 39 },
- { name: "big-bad-wolf", side: "werewolves", maxInGame: 1, recommendedMinPlayers: 15 },
- { name: "vile-father-of-wolves", side: "werewolves", maxInGame: 1, recommendedMinPlayers: 12 },
- { name: "white-werewolf", side: "werewolves", maxInGame: 1, recommendedMinPlayers: 12 },
- { name: "villager", side: "villagers", maxInGame: 39 },
- { name: "villager-villager", side: "villagers", maxInGame: 1 },
- { name: "seer", side: "villagers", maxInGame: 1 },
- { name: "cupid", side: "villagers", maxInGame: 1 },
- { name: "witch", side: "villagers", maxInGame: 1 },
- { name: "hunter", side: "villagers", maxInGame: 1 },
- { name: "little-girl", side: "villagers", maxInGame: 1 },
- { name: "guard", side: "villagers", maxInGame: 1 },
- { name: "ancient", side: "villagers", maxInGame: 1 },
- { name: "scapegoat", side: "villagers", maxInGame: 1 },
- { name: "idiot", side: "villagers", maxInGame: 1 },
- { name: "stuttering-judge", side: "villagers", maxInGame: 1 },
- { name: "two-sisters", side: "villagers", minInGame: 2, maxInGame: 2, recommendedMinPlayers: 12 },
- { name: "three-brothers", side: "villagers", minInGame: 3, maxInGame: 3, recommendedMinPlayers: 15 },
- { name: "wild-child", side: "villagers", maxInGame: 1 },
- { name: "dog-wolf", side: "villagers", maxInGame: 1 },
- { name: "thief", side: "villagers", maxInGame: 1 },
- { name: "angel", side: "villagers", maxInGame: 1 },
- { name: "pied-piper", side: "villagers", maxInGame: 1, recommendedMinPlayers: 12 },
- { name: "raven", side: "villagers", maxInGame: 1 },
+ { name: "werewolf", side: "werewolves", maxInGame: 99, type: "werewolf" },
+ { name: "big-bad-wolf", side: "werewolves", maxInGame: 1, recommendedMinPlayers: 15, type: "werewolf" },
+ { name: "vile-father-of-wolves", side: "werewolves", maxInGame: 1, recommendedMinPlayers: 12, type: "werewolf" },
+ { name: "white-werewolf", side: "werewolves", maxInGame: 1, recommendedMinPlayers: 12, type: "lonely" },
+ { name: "villager", side: "villagers", maxInGame: 99, type: "villager" },
+ { name: "villager-villager", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "seer", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "cupid", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "witch", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "hunter", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "little-girl", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "guard", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "ancient", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "scapegoat", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "idiot", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "two-sisters", side: "villagers", minInGame: 2, maxInGame: 2, recommendedMinPlayers: 12, type: "villager" },
+ { name: "three-brothers", side: "villagers", minInGame: 3, maxInGame: 3, recommendedMinPlayers: 15, type: "villager" },
+ { name: "fox", side: "villagers", maxInGame: 1, recommendedMinPlayers: 12, type: "villager" },
+ { name: "bear-tamer", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "stuttering-judge", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "rusty-sword-knight", side: "villagers", maxInGame: 1, type: "villager" },
+ { name: "thief", side: "villagers", maxInGame: 1, type: "ambiguous" },
+ { name: "wild-child", side: "villagers", maxInGame: 1, type: "ambiguous" },
+ { name: "dog-wolf", side: "villagers", maxInGame: 1, type: "ambiguous" },
+ { name: "angel", side: "villagers", maxInGame: 1, type: "lonely" },
+ { name: "pied-piper", side: "villagers", maxInGame: 1, recommendedMinPlayers: 12, type: "lonely" },
+ { name: "raven", side: "villagers", maxInGame: 1, type: "villager" },
];
exports.roleNames = this.roles.map(({ name }) => name);
\ No newline at end of file
diff --git a/src/helpers/constants/User.js b/src/helpers/constants/User.js
new file mode 100644
index 0000000..ce47994
--- /dev/null
+++ b/src/helpers/constants/User.js
@@ -0,0 +1 @@
+exports.registrationMethods = ["local", "facebook", "google"];
\ No newline at end of file
diff --git a/src/helpers/functions/Game.js b/src/helpers/functions/Game.js
index 2f3bc48..e0edfd7 100644
--- a/src/helpers/functions/Game.js
+++ b/src/helpers/functions/Game.js
@@ -28,10 +28,11 @@ exports.getRemainingWerewolvesToEat = game => game.players.filter(({ side, role,
role.current !== "white-werewolf");
exports.hasPiedPiperWon = game => {
+ const { isPowerlessIfInfected } = game.options.roles.piedPiper;
const piedPiperPlayer = this.getPlayerWithRole("pied-piper", game);
const remainingPlayersToCharm = this.getRemainingPlayersToCharm(game);
- return piedPiperPlayer?.isAlive && !doesPlayerHaveAttribute(piedPiperPlayer, "powerless") && piedPiperPlayer.side.current === "villagers" &&
- !remainingPlayersToCharm.length;
+ return piedPiperPlayer?.isAlive && !doesPlayerHaveAttribute(piedPiperPlayer, "powerless") &&
+ (!isPowerlessIfInfected || piedPiperPlayer.side.current === "villagers") && !remainingPlayersToCharm.length;
};
exports.hasAngelWon = game => {
@@ -108,4 +109,27 @@ exports.getVotesResults = () => JSON.parse(JSON.stringify(votesResults));
exports.getAdditionalCardsForRoleNames = () => JSON.parse(JSON.stringify(additionalCardsForRoleNames));
-exports.getAdditionalCardsThiefRoleNames = () => JSON.parse(JSON.stringify(additionalCardsThiefRoleNames));
\ No newline at end of file
+exports.getAdditionalCardsThiefRoleNames = () => JSON.parse(JSON.stringify(additionalCardsThiefRoleNames));
+
+exports.getNearestNeighbor = (playerId, players, direction, options = {}) => {
+ let checkedNeighborsCount = 0;
+ const player = players.find(({ _id }) => _id.toString() === playerId.toString());
+ if (!player) {
+ return null;
+ }
+ let checkingNeighborPosition = player.position;
+ while (checkedNeighborsCount < players.length) {
+ const checkingNeighbor = players[checkingNeighborPosition];
+ if (checkingNeighbor.position !== player.position && (!options.isAlive || checkingNeighbor.isAlive) &&
+ (!options.side || checkingNeighbor.side.current === options.side)) {
+ return checkingNeighbor;
+ }
+ if (direction === "left") {
+ checkingNeighborPosition = checkingNeighborPosition + 1 === players.length ? 0 : checkingNeighborPosition + 1;
+ } else if (direction === "right") {
+ checkingNeighborPosition = checkingNeighborPosition - 1 === -1 ? players.length - 1 : checkingNeighborPosition - 1;
+ }
+ checkedNeighborsCount++;
+ }
+ return null;
+};
\ No newline at end of file
diff --git a/src/helpers/functions/User.js b/src/helpers/functions/User.js
index 4df0476..e903b29 100644
--- a/src/helpers/functions/User.js
+++ b/src/helpers/functions/User.js
@@ -1,7 +1,10 @@
+const { registrationMethods } = require("../constants/User");
const { generateError } = require("./Error");
exports.checkJWTUserRights = (req, userId) => {
if (req.user.strategy === "JWT" && userId.toString() !== req.user._id.toString()) {
throw generateError("UNAUTHORIZED", "You can't access other's data.");
}
-};
\ No newline at end of file
+};
+
+exports.getRegistrationMethods = () => JSON.parse(JSON.stringify(registrationMethods));
\ No newline at end of file
diff --git a/src/routes/Game.js b/src/routes/Game.js
index cdbf237..b591457 100755
--- a/src/routes/Game.js
+++ b/src/routes/Game.js
@@ -4,7 +4,7 @@ const Game = require("../controllers/Game");
const GameHistory = require("../controllers/GameHistory");
const { getRoleNames, getSideNames } = require("../helpers/functions/Role");
const {
- getPatchableGameStatuses, getWaitingForPossibilities, getGameStatuses,
+ getPatchableGameStatuses, getWaitingForPossibilities, getGameStatuses, getGamePhases,
getGameRepartitionForbiddenRoleNames, getAdditionalCardsForRoleNames,
} = require("../helpers/functions/Game");
const { getPlayerActions } = require("../helpers/functions/Player");
@@ -26,16 +26,52 @@ module.exports = app => {
* @apiSuccess {String} status Game's current status. (_Possibilities: [Codes - Game Statuses](#game-statuses)_)
* @apiSuccess {AdditionalCard[]} [additionalCards] Game's additional cards. Set if `thief` is in the game. (_See: [Classes - Additional Card](#game-additional-card-class)_)
* @apiSuccess {Object} options Game's options.
+ * @apiSuccess {Object} options.repartition Game role's repartition.
+ * @apiSuccess {Boolean} options.repartition.isHidden=false If set to `true`, game's repartition will be hidden to all players. Default is false.
* @apiSuccess {Object} options.roles Game roles options.
+ * @apiSuccess {Boolean} options.roles.areRevealedOnDeath=true If set to `true`, player's role is revealed when he's dead. Default is `true`.
* @apiSuccess {Object} options.roles.sheriff Game sheriff role's options.
* @apiSuccess {Boolean} options.roles.sheriff.isEnabled=true If set to `true`, `sheriff` will be elected the first tick and the responsibility will be delegated when he dies. Otherwise, there will be no sheriff in the game and tie in votes will result in another vote between the tied players. In case of another equality, there will be no vote.
+ * @apiSuccess {Object} options.roles.sheriff.electedAt When the sheriff is elected during the game.
+ * @apiSuccess {Number} options.roles.sheriff.electedAt.turn=1 Game's turn when the sheriff is elected. Default is `1`.
+ * @apiSuccess {String} options.roles.sheriff.electedAt.phase="night" Game's phase when the sheriff is elected. Default is `night`.
* @apiSuccess {Boolean} options.roles.sheriff.hasDoubledVote=true If set to `true`, `sheriff` vote during the village's vote is doubled, otherwise, it's a regular vote.
+ * @apiSuccess {Object} options.roles.bigBadWolf Game big bad wolf role's options.
+ * @apiSuccess {Boolean} options.roles.bigBadWolf.isPowerlessIfWerewolfDies=true If set to `true`, `big-bad-wolf` won't wake up anymore during the night if at least one player from the `werewolves` side died. Default is `true`.
+ * @apiSuccess {Object} options.roles.whiteWerewolf Game white werewolf role's options.
+ * @apiSuccess {Number{>= 1 && <= 5}} options.roles.whiteWerewolf.wakingUpInterval=2 Since first `night`, interval of nights when the `white-werewolf` is waking up. Default is `2`, meaning he wakes up every other night.
* @apiSuccess {Object} options.roles.seer Game seer role's options.
* @apiSuccess {Boolean} options.roles.seer.isTalkative=true If set to `true`, the game master must say out loud what the seer saw during her night, otherwise, he must mime the seen role to the seer. Default is `true`.
+ * @apiSuccess {Boolean} options.roles.seer.canSeeRoles=true If set to `true`, the seer can the exact `role` of the target, otherwise, she only sees the `side`. Default is `true`.
+ * @apiSuccess {Object} options.roles.littleGirl Game little girl role's options.
+ * @apiSuccess {Boolean} options.roles.littleGirl.isProtectedByGuard=false If set to `false`, the little girl won't be protected by the guard from the werewolves attacks. Default is `false`.
+ * @apiSuccess {Object} options.roles.guard Game guard role's options.
+ * @apiSuccess {Boolean} options.roles.guard.canProtectTwice=false If set to `true`, the guard can protect twice in a row the same target. Default is `false`.
+ * @apiSuccess {Object} options.roles.ancient Game ancient role's options.
+ * @apiSuccess {Number{>= 1 && <= 5}} options.roles.ancient.livesCountAgainstWerewolves=2 Number of lives ancient has against `werewolves`. Default is `2`.
+ * @apiSuccess {Boolean} options.roles.ancient.doesTakeHisRevenge=true If set to `true`, the `ancient` will make all players from the `villagers` side `powerless` if he dies from them. Default is `true`.
+ * @apiSuccess {Object} options.roles.idiot Game idiot role's options.
+ * @apiSuccess {Boolean} options.roles.idiot.doesDieOnAncientDeath=true If set to `true`, the idiot will die if he is revealed and the ancient is dead. Default is `true`.
* @apiSuccess {Object} options.roles.twoSisters Game two sisters role's options.
* @apiSuccess {Number{>= 0 && <= 5}} options.roles.twoSisters.wakingUpInterval=2 Since first `night`, interval of nights when the Two Sisters are waking up. Default is `2`, meaning they wake up every other night. If set to `0`, they are waking up the first night only.
* @apiSuccess {Object} options.roles.threeBrothers Game three brothers role's options.
* @apiSuccess {Number{>= 0 && <= 5}} options.roles.threeBrothers.wakingUpInterval=2 Since first `night`, interval of nights when the Three Brothers are waking up. Default is `2`, meaning they wake up every other night. If set to `0`, they are waking up the first night only.
+ * @apiSuccess {Object} options.roles.fox Game fox role's options.
+ * @apiSuccess {Boolean} options.roles.fox.isPowerlessIfMissesWerewolf=true If set to `true`, the fox will loose his power if he doesn't find a player from the `werewolves` side during his turn if he doesn't skip. Default is `true`.
+ * @apiSuccess {Object} options.roles.bearTamer Game bear tamer role's options.
+ * @apiSuccess {Boolean} options.roles.bearTamer.doesGrowlIfInfected=true If set to `true`, the bear tamer will have the `growls` attribute until he dies if he is `infected`. Default is `true`.
+ * @apiSuccess {Object} options.roles.stutteringJudge Game stuttering judge role's options.
+ * @apiSuccess {Number{>= 1 && <= 5}} options.roles.stutteringJudge.voteRequestsCount=1 Number of vote requests that the `stuttering-judge` can make during the game. Default is `1`.
+ * @apiSuccess {Object} options.roles.wildChild Game wild child role's options.
+ * @apiSuccess {Boolean} options.roles.wildChild.isTransformationRevealed=false If set to `true`, when `wild-child` joins the `werewolves` side because his model died, the game master will announce his transformation to other players. Default is `false`.
+ * @apiSuccess {Object} options.roles.dogWolf Game dog wolf role's options.
+ * @apiSuccess {Boolean} options.roles.dogWolf.isChosenSideRevealed=false If set to `true`, when `dog-wolf` chooses his side at the beginning of the game, the game master will announce the chosen side to other players. Default is `false`.
+ * @apiSuccess {Object} options.roles.thief Game thief role's options.
+ * @apiSuccess {Boolean} options.roles.thief.mustChooseBetweenWerewolves=true If set to `true`, if all `thief` additional cards are from the `werewolves` side, he can't skip and must choose one. Default is `true`.
+ * @apiSuccess {Number{>= 1 && <= 5}} options.roles.thief.additionalCardsCount=2 Number of additional cards for the `thief` at the beginning of the game. Default is `2`.
+ * @apiSuccess {Object} options.roles.piedPiper Game pied piper role's options.
+ * @apiSuccess {Number{>= 1 && <= 5}} options.roles.piedPiper.charmedPeopleCountPerNight=2 Number of charmed people by the `pied-piper` per night if there are enough targets (or number of not charmed players otherwise). Default is `2`.
+ * @apiSuccess {Boolean} options.roles.piedPiper.isPowerlessIfInfected=true If set to `true`, `pied-piper` will be powerless if he is infected by the `vile-father-of-wolves`. Default is `true`.
* @apiSuccess {Object} options.roles.raven Game raven role's options.
* @apiSuccess {Number{>= 1 && <= 5}} options.roles.raven.markPenalty=2 Penalty of votes against the player targeted by the raven mark for the next village's vote. Default is `2`, meaning that the raven marked player will have two votes against himself.
* @apiSuccess {GameHistory[]} history Game's history. (_See: [Classes - Game History](#game-history-class)_)
@@ -165,24 +201,57 @@ module.exports = app => {
* @apiParam (Request Body Parameters) {Object[]} players Must contain between 4 and 40 players.
* @apiParam (Request Body Parameters) {String{>= 1 && <= 30}} players.name Player's name. Must be unique in the array and between 1 and 30 characters long.
* @apiParam (Request Body Parameters) {String} players.role Player's role. (_See [Codes - Player Roles](#player-roles)_)
+ * @apiParam (Request Body Parameters) {Number{>= 0}} [players.position] Player's unique position among all players. Maximum is `players.length - 1`. Either all players position must be set or none of them. In that last case, it will be generated automatically.
* @apiParam (Request Body Parameters) {Object[]} [additionalCards] Game's additional cards. Must be set if role `thief` is in the game and contain 2 cards.
* @apiParam (Request Body Parameters) {String} additionalCards.role Additional card's role. The role must be still available compared to the game's composition. (_See [Codes - Player Roles](#player-roles)_)
* @apiParam (Request Body Parameters) {String} additionalCards.for Additional card's recipient. Must be equal to `thief`.
* @apiParam (Request Body Parameters) {Object} [options] Game's options.
+ * @apiParam (Request Body Parameters) {Object} [options.repartition] Game repartition's options.
+ * @apiParam (Request Body Parameters) {Boolean} [options.repartition.isHidden=false] If set to `true`, game's repartition will be hidden to all players.
* @apiParam (Request Body Parameters) {Object} [options.roles] Game roles options.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.areRevealedOnDeath=true] If set to `true`, player's role is revealed when he's dead.
* @apiParam (Request Body Parameters) {Object} [options.roles.sheriff] Game sheriff role's options.
* @apiParam (Request Body Parameters) {Boolean} [options.roles.sheriff.isEnabled=true] If set to `true`, `sheriff` will be elected the first tick and the responsibility will be delegated when he dies. Otherwise, there will be no sheriff in the game and tie in votes will result in another vote between the tied players. In case of another equality, there will be no vote.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.sheriff.electedAt] When the sheriff is elected during the game.
+ * @apiParam (Request Body Parameters) {Number{>= 1 && <= 5}} [options.roles.sheriff.electedAt.turn=1] When the sheriff is elected during the game.
+ * @apiParam (Request Body Parameters) {String{"night", "day"}} [options.roles.sheriff.electedAt.phase="night"] When the sheriff is elected during the game.
* @apiParam (Request Body Parameters) {Boolean} [options.roles.sheriff.hasDoubledVote=true] If set to `true`, `sheriff` vote during the village's vote is doubled, otherwise, it's a regular vote.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.bigBadWolf] Game big bad wolf role's options.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.bigBadWolf.isPowerlessIfWerewolfDies=true] If set to `true`, `big-bad-wolf` won't wake up anymore during the night if at least one player from the `werewolves` side died. Default is `true`.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.whiteWerewolf] Game white werewolf role's options.
+ * @apiParam (Request Body Parameters) {Number{>= 1 && <= 5}} [options.roles.whiteWerewolf.wakingUpInterval=2] Since first `night`, interval of nights when the `white-werewolf` is waking up. Default is `2`, meaning he wakes up every other night.
* @apiParam (Request Body Parameters) {Object} [options.roles.seer] Game seer role's options.
* @apiParam (Request Body Parameters) {Boolean} [options.roles.seer.isTalkative=true] If set to `true`, the game master must say out loud what the seer saw during her night, otherwise, he must mime the seen role to the seer. Default is `true`.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.seer.canSeeRoles=true] If set to `true`, the seer can the exact `role` of the target, otherwise, she only sees the `side`. Default is `true`.
* @apiParam (Request Body Parameters) {Object} [options.roles.littleGirl] Game little girl role's options.
* @apiParam (Request Body Parameters) {Boolean} [options.roles.littleGirl.isProtectedByGuard=false] If set to `false`, the little girl won't be protected by the guard from the werewolves attacks. Default is `false`.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.guard] Game guard role's options.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.guard.canProtectTwice=false] If set to `true`, the guard can protect twice in a row the same target. Default is `false`.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.ancient] Game ancient role's options.
+ * @apiParam (Request Body Parameters) {Number{>= 1 && <= 5}} [options.roles.ancient.livesCountAgainstWerewolves=2] Number of lives ancient has against `werewolves`. Default is `2`.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.ancient.doesTakeHisRevenge=true] If set to `true`, the `ancient` will make all players from the `villagers` side `powerless` if he dies from them. Default is `true`.
* @apiParam (Request Body Parameters) {Object} [options.roles.idiot] Game idiot role's options.
* @apiParam (Request Body Parameters) {Boolean} [options.roles.idiot.doesDieOnAncientDeath=true] If set to `true`, the idiot will die if he is revealed and the ancient is dead. Default is `true`.
* @apiParam (Request Body Parameters) {Object} [options.roles.twoSisters] Game two sisters role's options.
* @apiParam (Request Body Parameters) {Number{>= 0 && <= 5}} [options.roles.twoSisters.wakingUpInterval=2] Since first `night`, interval of nights when the Two Sisters are waking up. Default is `2`, meaning they wake up every other night. If set to `0`, they are waking up the first night only.
* @apiParam (Request Body Parameters) {Object} [options.roles.threeBrothers] Game three brothers role's options.
* @apiParam (Request Body Parameters) {Number{>= 0 && <= 5}} [options.roles.threeBrothers.wakingUpInterval=2] Since first `night`, interval of nights when the Three Brothers are waking up. Default is `2`, meaning they wake up every other night. If set to `0`, they are waking up the first night only.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.fox] Game fox's role options.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.fox.isPowerlessIfMissesWerewolf=true] If set to `true`, the fox will loose his power if he doesn't find a player from the `werewolves` side during his turn if he doesn't skip. Default is `true`.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.bearTamer] Game bear tamer's role options.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.bearTamer.doesGrowlIfInfected=true] If set to `true`, the bear tamer will have the `growls` attribute until he dies if he is `infected`. Default is `true`.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.stutteringJudge] Game stuttering judge's role options.
+ * @apiParam (Request Body Parameters) {Number{>= 1 && <= 5}} [options.roles.stutteringJudge.voteRequestsCount=1] Number of vote requests that the `stuttering-judge` can make during the game. Default is `1`.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.wildChild] Game wild child's role options.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.wildChild.isTransformationRevealed=false] If set to `true`, when `wild-child` joins the `werewolves` side because his model died, the game master will announce his transformation to other players. Default is `false`.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.dogWolf] Game dog wolf's role options.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.dogWolf.isChosenSideRevealed=false] If set to `true`, when `dog-wolf` chooses his side at the beginning of the game, the game master will announce the chosen side to other players. Default is `false`.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.thief] Game thief's role options.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.thief.mustChooseBetweenWerewolves=true] If set to `true`, if all `thief` additional cards are from the `werewolves` side, he can't skip and must choose one. Default is `true`.
+ * @apiParam (Request Body Parameters) {Number{>= 1 && <= 5}} [options.roles.thief.additionalCardsCount =2] Number of additional cards for the `thief` at the beginning of the game. Default is `2`.
+ * @apiParam (Request Body Parameters) {Object} [options.roles.piedPiper] Game pied piper's role options.
+ * @apiParam (Request Body Parameters) {Number{>= 1 && <= 5}} [options.roles.piedPiper.charmedPeopleCountPerNight=2] Number of charmed people by the `pied-piper` per night if there are enough targets (or number of not charmed players otherwise). Default is `2`.
+ * @apiParam (Request Body Parameters) {Boolean} [options.roles.piedPiper.isPowerlessIfInfected=true] If set to `true`, `pied-piper` will be powerless if he is infected by the `vile-father-of-wolves`. Default is `true`.
* @apiParam (Request Body Parameters) {Object} [options.roles.raven] Game raven's role options.
* @apiParam (Request Body Parameters) {Number{>= 1 && <= 5}} [options.roles.raven.markPenalty=2] Penalty of votes against the player targeted by the raven mark for the next village's vote. Default is `2`, meaning that the raven marked player will have two votes against himself.
* @apiUse GameResponse
@@ -199,33 +268,75 @@ module.exports = app => {
body("players.*.role")
.isString().withMessage("Must be a valid string")
.isIn(getRoleNames()).withMessage(`Must be equal to one of the following values: ${getRoleNames()}`),
+ body("players.*.position")
+ .optional()
+ .isInt({ min: 0 }).withMessage("Must be a valid integer greater or equal than 0")
+ .toInt(),
body("additionalCards")
.optional()
- .isArray().withMessage("Must be a valid array")
- .custom(value => value.length === 2 ? Promise.resolve() : Promise.reject(new Error()))
- .withMessage("Must contain 2 cards"),
+ .isArray().withMessage("Must be a valid array"),
body("additionalCards.*.role")
.isString().withMessage("Must be a valid string")
.isIn(getRoleNames()).withMessage(`Must be equal to one of the following values: ${getRoleNames()}`),
body("additionalCards.*.for")
.isString().withMessage("Must be a valid string")
.isIn(getAdditionalCardsForRoleNames()).withMessage(`Must be equal to one of the following values: ${getAdditionalCardsForRoleNames()}`),
+ body("options.repartition.isHidden")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
+ body("options.roles.areRevealedOnDeath")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
body("options.roles.sheriff.isEnabled")
.optional()
.isBoolean().withMessage("Must be a valid boolean")
.toBoolean(),
+ body("options.roles.sheriff.electedAt.turn")
+ .optional()
+ .isInt({ min: 1, max: 5 }).withMessage("Must be a valid integer between 1 and 5")
+ .toInt(),
+ body("options.roles.sheriff.electedAt.phase")
+ .optional()
+ .isString().withMessage("Must be a valid string")
+ .isIn(getGamePhases()).withMessage(`Must be equal to one of the following values: ${getGamePhases()}`),
body("options.roles.sheriff.hasDoubledVote")
.optional()
.isBoolean().withMessage("Must be a valid boolean")
.toBoolean(),
+ body("options.roles.bigBadWolf.isPowerlessIfWerewolfDies")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
+ body("options.roles.whiteWerewolf.wakingUpInterval")
+ .optional()
+ .isInt({ min: 1, max: 5 }).withMessage("Must be a valid integer between 1 and 5")
+ .toInt(),
body("options.roles.seer.isTalkative")
.optional()
.isBoolean().withMessage("Must be a valid boolean")
.toBoolean(),
+ body("options.roles.seer.canSeeRoles")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
body("options.roles.littleGirl.isProtectedByGuard")
.optional()
.isBoolean().withMessage("Must be a valid boolean")
.toBoolean(),
+ body("options.roles.guard.canProtectTwice")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
+ body("options.roles.ancient.livesCountAgainstWerewolves")
+ .optional()
+ .isInt({ min: 1, max: 5 }).withMessage("Must be a valid integer between 0 and 5")
+ .toInt(),
+ body("options.roles.ancient.doesTakeHisRevenge")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
body("options.roles.idiot.doesDieOnAncientDeath")
.optional()
.isBoolean().withMessage("Must be a valid boolean")
@@ -238,6 +349,42 @@ module.exports = app => {
.optional()
.isInt({ min: 0, max: 5 }).withMessage("Must be a valid integer between 0 and 5")
.toInt(),
+ body("options.roles.fox.isPowerlessIfMissesWerewolf")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
+ body("options.roles.bearTamer.doesGrowlIfInfected")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
+ body("options.roles.stutteringJudge.voteRequestsCount")
+ .optional()
+ .isInt({ min: 1, max: 5 }).withMessage("Must be a valid integer between 1 and 5")
+ .toInt(),
+ body("options.roles.wildChild.isTransformationRevealed")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
+ body("options.roles.dogWolf.isChosenSideRevealed")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
+ body("options.roles.thief.mustChooseBetweenWerewolves")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
+ body("options.roles.thief.additionalCardsCount")
+ .optional()
+ .isInt({ min: 1, max: 5 }).withMessage("Must be a valid integer between 1 and 5")
+ .toInt(),
+ body("options.roles.piedPiper.charmedPeopleCountPerNight")
+ .optional()
+ .isInt({ min: 1, max: 5 }).withMessage("Must be a valid integer between 1 and 5")
+ .toInt(),
+ body("options.roles.piedPiper.isPowerlessIfInfected")
+ .optional()
+ .isBoolean().withMessage("Must be a valid boolean")
+ .toBoolean(),
body("options.roles.raven.markPenalty")
.optional()
.isInt({ min: 1, max: 5 }).withMessage("Must be a valid integer between 1 and 5")
diff --git a/src/routes/Role.js b/src/routes/Role.js
index 9ff0d5e..39bc0fb 100644
--- a/src/routes/Role.js
+++ b/src/routes/Role.js
@@ -3,8 +3,11 @@ const { getRoles } = require("../helpers/functions/Role");
/**
* @apiDefine RoleResponse
* @apiSuccess {String} name Role's name. (_Possibilities: [Codes - Player Roles](#player-roles)_)
- * @apiSuccess {String} group Role's group. (_Possibilities: [Codes - Player Groups](#player-groups)_)
+ * @apiSuccess {String} side Role's original side. (_Possibilities: [Codes - Player Sides](#player-sides)_)
+ * @apiSuccess {String} type Role's type. (_Possibilities: `villager`, `werewolf`, `ambiguous`, `lonely`_)
+ * @apiSuccess {Number} [minInGame] If the role is chosen by at least one player, then minimum X players must choose it to start the game.
* @apiSuccess {Number} maxInGame Maximum of this role in a game.
+ * @apiSuccess {Number} [recommendedMinPlayers] It is recommended to have at least X players in game for choosing this role.
*/
module.exports = app => {
diff --git a/src/routes/User.js b/src/routes/User.js
index 0512291..b2429cf 100755
--- a/src/routes/User.js
+++ b/src/routes/User.js
@@ -22,6 +22,8 @@ module.exports = app => {
* @apiDefine UserResponse
* @apiSuccess {ObjectID} _id User's ID.
* @apiSuccess {String} email User's email.
+ * @apiSuccess {Object} registration User's registration data.
+ * @apiSuccess {String} registration.method How the user registered himself. (_Possibilities: `local`, `facebook` or `google`_)
* @apiSuccess {Date} createdAt When the user is created.
* @apiSuccess {Date} updatedAt When the user is updated.
*/
@@ -95,4 +97,30 @@ module.exports = app => {
.isString().withMessage("Must be a string")
.isLength({ min: 5, max: 50 }).withMessage("Must be at least 5 characters long"),
], User.login);
+
+ /**
+ * @api {POST} /users/login/facebook E] Login with Facebook
+ * @apiName LoginFacebookUser
+ * @apiGroup Users ๐ค
+ *
+ * @apiParam (Request Body Parameters) {String} accessToken Facebook user's access token for the Werewolves Assistant app.
+ * @apiSuccess {String} token JSON Web Token to keep for further route authentication.
+ */
+ app.post("/users/login/facebook", [
+ body("accessToken")
+ .isString().withMessage("Must be a valid string"),
+ ], User.loginWithFacebook);
+
+ /**
+ * @api {POST} /users/login/facebook F] Login with Google
+ * @apiName LoginGoogleUser
+ * @apiGroup Users ๐ค
+ *
+ * @apiParam (Request Body Parameters) {String} idToken Google user's id token for the Werewolves Assistant app.
+ * @apiSuccess {String} token JSON Web Token to keep for further route authentication.
+ */
+ app.post("/users/login/google", [
+ body("idToken")
+ .isString().withMessage("Must be a valid string"),
+ ], User.loginWithGoogle);
};
\ No newline at end of file
diff --git a/src/routes/index.js b/src/routes/index.js
index 90cde5f..a69ad4e 100755
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -12,7 +12,7 @@ module.exports = app => {
* @apiSuccess {String} version API's version
*/
app.route("/").get((req, res) => {
- res.status(200).json({ name: "๐บ Werewolves Assistant API", version: "0.10.0" });
+ res.status(200).json({ name: "๐บ Werewolves Assistant API", version: "0.11.0" });
});
return;
}
diff --git a/tests/e2e/app.test.js b/tests/e2e/app.test.js
index d4f2ae3..944fa38 100644
--- a/tests/e2e/app.test.js
+++ b/tests/e2e/app.test.js
@@ -5,15 +5,18 @@ const chaiHttp = require("chai-http");
chai.use(chaiHttp);
const { expect } = chai;
+let server;
-describe("Testing main route", () => {
- before(done => !app.isReady ? app.on("ready", done) : done);
+describe("E2E - Testing main route", () => {
+ before(done => {
+ server = app.listen(3000, done);
+ });
it("๐ Welcomes user with API name", done => {
- chai.request(app)
+ chai.request(server)
.get("/")
.end((err, res) => {
expect(res).to.have.status(200);
- expect(res.body.name).to.equals("๐บ Werewolves Assistant API");
+ expect(res.body.name).to.equal("๐บ Werewolves Assistant API");
done();
});
});
diff --git a/tests/e2e/game/ancient-infected.test.js b/tests/e2e/game/ancient-infected.test.js
index 8ba7ba4..18fef17 100644
--- a/tests/e2e/game/ancient-infected.test.js
+++ b/tests/e2e/game/ancient-infected.test.js
@@ -16,13 +16,16 @@ let players = [
{ name: "Dโฌg", role: "ancient" },
{ name: "Dรg", role: "villager" },
];
-let token, game;
+let server, token, game;
describe("Q - Game with an ancient who is infected after his first life and 2 protections", () => {
before(done => resetDatabase(done));
+ before(done => {
+ server = app.listen(3000, done);
+ });
after(done => resetDatabase(done));
it("๐ค Creates new user (POST /users)", done => {
- chai.request(app)
+ chai.request(server)
.post("/users")
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -32,7 +35,7 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
});
});
it("๐ Logs in successfully (POST /users/login)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/users/login`)
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -43,7 +46,7 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
});
});
it("๐ฒ Creates game with JWT auth (POST /games)", done => {
- chai.request(app)
+ chai.request(server)
.post("/games")
.set({ Authorization: `Bearer ${token}` })
.send({ players, options: { roles: { sheriff: { isEnabled: false } } } })
@@ -55,12 +58,12 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
});
it("๐ Night falls", done => {
players = game.players;
- expect(game.phase).to.equals("night");
+ expect(game.phase).to.equal("night");
done();
});
it("๐ก Guard protects himself (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[1]._id }] })
@@ -69,13 +72,13 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
game = res.body;
expect(game.players[1].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[1]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[1]._id);
done();
});
});
it("๐บ Werewolf eats the ancient (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[3]._id }] })
@@ -83,14 +86,14 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
expect(res).to.have.status(200);
game = res.body;
expect(game.players[3].attributes).to.deep.include({ name: "eaten", source: "werewolves", remainingPhases: 1 });
- expect(game.players[3].side.current).to.equals("villagers");
+ expect(game.players[3].side.current).to.equal("villagers");
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[3]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[3]._id);
done();
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion" })
@@ -101,14 +104,14 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
});
});
it("โ๏ธ Sun is rising and ancient is alive because hhe has another life", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[3].isAlive).to.be.true;
expect(game.players[3].role.isRevealed).to.be.false;
done();
});
it("๐ช All vote for the villager (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[1]._id, for: players[4]._id }] })
@@ -122,7 +125,7 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
});
it("๐ก Guard protects the ancient (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[3]._id }] })
@@ -131,13 +134,13 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
game = res.body;
expect(game.players[3].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[3]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[3]._id);
done();
});
});
it("๐บ Werewolf eats the ancient again (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[3]._id }] })
@@ -145,12 +148,12 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[3]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[3]._id);
done();
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion" })
@@ -161,14 +164,14 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
});
});
it("โ๏ธ Sun is rising and ancient is alive because guard saved him", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[3].isAlive).to.be.true;
expect(game.players[3].role.isRevealed).to.be.false;
done();
});
it("๐ช All vote for the guard (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[1]._id }] })
@@ -182,7 +185,7 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
});
it("๐บ Werewolf eats the ancient again, again (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[3]._id }] })
@@ -190,12 +193,12 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[3]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[3]._id);
done();
});
});
it("๐ช Witch uses her life potion on ancient (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [{ player: players[3]._id, hasDrankLifePotion: true }] })
@@ -206,14 +209,14 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
});
});
it("โ๏ธ Sun is rising and ancient is alive because witch saved him", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[3].isAlive).to.be.true;
expect(game.players[3].role.isRevealed).to.be.false;
done();
});
it("๐ช All vote for the witch (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[0]._id }] })
@@ -227,7 +230,7 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
});
it("๐บ Vile father of wolves infects the ancient because he knows he has no life ! (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[3]._id, isInfected: true }] })
@@ -235,12 +238,12 @@ describe("Q - Game with an ancient who is infected after his first life and 2 pr
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[3]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[3]._id);
done();
});
});
it("โ๏ธ Sun is rising and ancient has become a werewolf", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[3].isAlive).to.be.true;
expect(game.players[3].role.isRevealed).to.be.false;
expect(game.players[3].side.current).to.equal("werewolves");
diff --git a/tests/e2e/game/ancient-revenge-game.test.js b/tests/e2e/game/ancient-revenge-game.test.js
index c073143..3247cb2 100644
--- a/tests/e2e/game/ancient-revenge-game.test.js
+++ b/tests/e2e/game/ancient-revenge-game.test.js
@@ -31,18 +31,25 @@ let players = [
{ name: "Dฮฉg", role: "dog-wolf" },
{ name: "D#g", role: "cupid" },
{ name: "Dยฑg", role: "thief" },
+ { name: "Dยปg", role: "fox" },
+ { name: "Dโg", role: "bear-tamer" },
+ { name: "Dโg", role: "werewolf" },
+ { name: "Dลg", role: "rusty-sword-knight" },
];
const additionalCards = [
{ role: "werewolf", for: "thief" },
{ role: "werewolf", for: "thief" },
];
-let token, game;
+let server, token, game;
describe("L - Game with various villagers who loose their power because they kill ancient", () => {
before(done => resetDatabase(done));
+ before(done => {
+ server = app.listen(3000, done);
+ });
after(done => resetDatabase(done));
it("๐ค Creates new user (POST /users)", done => {
- chai.request(app)
+ chai.request(server)
.post("/users")
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -52,7 +59,7 @@ describe("L - Game with various villagers who loose their power because they kil
});
});
it("๐ Logs in successfully (POST /users/login)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/users/login`)
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -63,7 +70,7 @@ describe("L - Game with various villagers who loose their power because they kil
});
});
it("๐ฒ Creates game with JWT auth (POST /games)", done => {
- chai.request(app)
+ chai.request(server)
.post("/games")
.set({ Authorization: `Bearer ${token}` })
.send({ players, additionalCards })
@@ -75,12 +82,12 @@ describe("L - Game with various villagers who loose their power because they kil
});
it("๐ Night falls", done => {
players = game.players;
- expect(game.phase).to.equals("night");
+ expect(game.phase).to.equal("night");
done();
});
it("๐ช All elect the idiot as the sheriff (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "elect-sheriff", votes: [{ from: players[0]._id, for: players[15]._id }] })
@@ -90,10 +97,10 @@ describe("L - Game with various villagers who loose their power because they kil
expect(game.players[15].attributes).to.deep.include({ name: "sheriff", source: "all" });
expect(game.history).to.be.an("array").to.have.lengthOf(1);
expect(game.history[0].play.votes).to.exist;
- expect(game.history[0].play.votes[0].from._id).to.equals(game.players[0]._id);
- expect(game.history[0].play.votes[0].for._id).to.equals(game.players[15]._id);
+ expect(game.history[0].play.votes[0].from._id).to.equal(game.players[0]._id);
+ expect(game.history[0].play.votes[0].for._id).to.equal(game.players[15]._id);
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(game.players[15]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(game.players[15]._id);
expect(game.history[0].play.source.name).to.equal("all");
expect(game.history[0].play.source.players).to.be.an("array").to.have.lengthOf(players.length);
expect(game.history[0].deadPlayers).to.not.exist;
@@ -102,7 +109,7 @@ describe("L - Game with various villagers who loose their power because they kil
});
it("๐ช All vote for the ancient, revenge is on: all villagers are powerless (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[0]._id, for: players[12]._id }] })
@@ -123,7 +130,7 @@ describe("L - Game with various villagers who loose their power because they kil
expect(game.players[9].attributes).to.deep.include({ name: "powerless", source: "ancient" });
expect(game.players[10].attributes).to.deep.include({ name: "powerless", source: "ancient" });
expect(game.players[11].attributes).to.deep.include({ name: "powerless", source: "ancient" });
- expect(game.players[11].side.current).to.equals("villagers");
+ expect(game.players[11].side.current).to.equal("villagers");
expect(game.players[13].attributes).to.deep.include({ name: "powerless", source: "ancient" });
expect(game.players[14].attributes).to.deep.include({ name: "powerless", source: "ancient" });
expect(game.players[15].attributes).to.deep.include({ name: "powerless", source: "ancient" });
@@ -132,12 +139,15 @@ describe("L - Game with various villagers who loose their power because they kil
expect(game.players[18].attributes).to.deep.include({ name: "powerless", source: "ancient" });
expect(game.players[19].attributes).to.deep.include({ name: "powerless", source: "ancient" });
expect(game.players[20].attributes).to.deep.include({ name: "powerless", source: "ancient" });
+ expect(game.players[21].attributes).to.deep.include({ name: "powerless", source: "ancient" });
+ expect(game.players[22].attributes).to.deep.include({ name: "powerless", source: "ancient" });
+ expect(game.players[24].attributes).to.deep.include({ name: "powerless", source: "ancient" });
done();
});
});
it("๐บ Werewolf eats the angel (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[17]._id }] })
@@ -145,18 +155,19 @@ describe("L - Game with various villagers who loose their power because they kil
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[17]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[17]._id);
done();
});
});
it("โ๏ธ Sun is rising", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[17].isAlive).to.be.false;
+ expect(game.players[22].attributes).to.not.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
done();
});
it("๐ช All vote for one brother (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[1]._id, for: players[9]._id }] })
@@ -169,16 +180,16 @@ describe("L - Game with various villagers who loose their power because they kil
});
it("๐บ Werewolf eats the guard (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[4]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.players[4].side.current).to.equals("villagers");
+ expect(game.players[4].side.current).to.equal("villagers");
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[4]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[4]._id);
expect(game.players[4].isAlive).to.be.false;
expect(game.players[4].attributes).to.deep.includes({ name: "powerless", source: "ancient" });
expect(game.players[4].attributes).to.not.deep.includes({ name: "eaten", source: "werewolves" });
@@ -187,7 +198,7 @@ describe("L - Game with various villagers who loose their power because they kil
});
it("๐ช All vote for the raven (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[0]._id, for: players[3]._id }] })
@@ -205,7 +216,7 @@ describe("L - Game with various villagers who loose their power because they kil
});
it("๐บ Werewolf is the only one called during the night and eats the witch (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[2]._id }] })
@@ -213,13 +224,13 @@ describe("L - Game with various villagers who loose their power because they kil
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
done();
});
});
it("โ๏ธ Stuttering judge can't request another vote if he is powerless (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -230,13 +241,13 @@ describe("L - Game with various villagers who loose their power because they kil
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("STUTTERING_JUDGE_POWERLESS");
+ expect(res.body.type).to.equal("STUTTERING_JUDGE_POWERLESS");
done();
});
});
it("๐ช Tie in vote between the idiot and one sister (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -259,7 +270,7 @@ describe("L - Game with various villagers who loose their power because they kil
});
it("๐ Sheriff settles votes by choosing the sister (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "settle-votes", targets: [{ player: players[6]._id }] })
@@ -271,23 +282,24 @@ describe("L - Game with various villagers who loose their power because they kil
done();
});
});
- it("๐บ Werewolf is the only one called during the night and eats the other sister (POST /games/:id/play)", done => {
+ it("๐บ Werewolf is the only one called during the night and eats the rusty sword knight (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "werewolves", action: "eat", targets: [{ player: players[7]._id }] })
+ .send({ source: "werewolves", action: "eat", targets: [{ player: players[24]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
+ expect(game.players[5].attributes).to.not.exist;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[7]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[24]._id);
done();
});
});
it("๐ช All vote for the idiot who is the sheriff, he dies from votes because he's powerless (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[5]._id, for: players[15]._id }] })
@@ -305,7 +317,7 @@ describe("L - Game with various villagers who loose their power because they kil
});
it("๐ Sheriff delegates to the werewolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate", targets: [{ player: players[5]._id }] })
@@ -314,7 +326,7 @@ describe("L - Game with various villagers who loose their power because they kil
game = res.body;
expect(game.players[5].attributes).to.deep.include({ name: "sheriff", source: "sheriff" });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(game.players[5]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(game.players[5]._id);
done();
});
});
diff --git a/tests/e2e/game/bear-tamer-infected.test.js b/tests/e2e/game/bear-tamer-infected.test.js
new file mode 100644
index 0000000..9ad0be8
--- /dev/null
+++ b/tests/e2e/game/bear-tamer-infected.test.js
@@ -0,0 +1,105 @@
+const { describe, it, before, after } = require("mocha");
+const chai = require("chai");
+const chaiHttp = require("chai-http");
+const app = require("../../../app");
+const Config = require("../../../config");
+const { resetDatabase } = require("../../../src/helpers/functions/Test");
+
+chai.use(chaiHttp);
+const { expect } = chai;
+
+const credentials = { email: "test@test.fr", password: "secret" };
+const originalPlayers = [
+ { name: "Dag", role: "vile-father-of-wolves" },
+ { name: "Dig", role: "villager" },
+ { name: "Deg", role: "bear-tamer" },
+ { name: "Dog", role: "villager" },
+ { name: "Dรธg", role: "villager" },
+];
+let server, token, game, players;
+
+describe("X - Tiny game of 5 players in which the bear tamer is infected and so, growls every time", () => {
+ before(done => resetDatabase(done));
+ before(done => {
+ server = app.listen(3000, done);
+ });
+ after(done => resetDatabase(done));
+ it("๐ค Creates new user (POST /users)", done => {
+ chai.request(server)
+ .post("/users")
+ .auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
+ .send(credentials)
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ done();
+ });
+ });
+ it("๐ Logs in successfully (POST /users/login)", done => {
+ chai.request(server)
+ .post(`/users/login`)
+ .auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
+ .send(credentials)
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ token = res.body.token;
+ done();
+ });
+ });
+ it("๐ฒ Creates game with JWT auth (POST /games)", done => {
+ chai.request(server)
+ .post("/games")
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ players: originalPlayers, options: { roles: { sheriff: { isEnabled: false } } } })
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ game = res.body;
+ done();
+ });
+ });
+ it("๐บ Vile father of wolf infected the bear tamer (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "werewolves", action: "eat", targets: [{ player: players[2]._id, isInfected: true }] })
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ game = res.body;
+ done();
+ });
+ });
+ it("โ๏ธ Sun is rising and bear tamer growls because he is infected, even if he doesn't have any werewolves neighbors", done => {
+ expect(game.players[2].attributes).to.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
+ done();
+ });
+ it("๐ช All vote for the vile father of wolves (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "all", action: "vote", votes: [{ from: players[1]._id, for: players[0]._id }] })
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ game = res.body;
+ expect(game.players[0].isAlive).to.be.false;
+ expect(game.players[0].murdered).to.deep.equals({ by: "all", of: "vote" });
+ done();
+ });
+ });
+ it("๐บ Infected bear tamer eats the first villager (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "werewolves", action: "eat", targets: [{ player: players[1]._id }] })
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ game = res.body;
+ done();
+ });
+ });
+ it("โ๏ธ Sun is rising and bear tamer growls because he is infected, even if he doesn't have any werewolves neighbors", done => {
+ expect(game.players[2].attributes).to.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
+ done();
+ });
+});
\ No newline at end of file
diff --git a/tests/e2e/game/changes-during-night.test.js b/tests/e2e/game/changes-during-night.test.js
index b1b9484..199327b 100644
--- a/tests/e2e/game/changes-during-night.test.js
+++ b/tests/e2e/game/changes-during-night.test.js
@@ -16,13 +16,16 @@ const originalPlayers = [
{ name: "Dog", role: "seer" },
{ name: "Dug", role: "witch" },
];
-let token, game, players;
+let server, token, game, players;
describe("V - Tiny game of 5 players in which because of the early votes, actions during night change", () => {
before(done => resetDatabase(done));
+ before(done => {
+ server = app.listen(3000, done);
+ });
after(done => resetDatabase(done));
it("๐ค Creates new user (POST /users)", done => {
- chai.request(app)
+ chai.request(server)
.post("/users")
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -32,7 +35,7 @@ describe("V - Tiny game of 5 players in which because of the early votes, action
});
});
it("๐ Logs in successfully (POST /users/login)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/users/login`)
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -43,7 +46,7 @@ describe("V - Tiny game of 5 players in which because of the early votes, action
});
});
it("๐ฒ Creates game with JWT auth (POST /games)", done => {
- chai.request(app)
+ chai.request(server)
.post("/games")
.set({ Authorization: `Bearer ${token}` })
.send({ players: originalPlayers })
@@ -55,7 +58,7 @@ describe("V - Tiny game of 5 players in which because of the early votes, action
});
it("๐ช All elect the hunter as the sheriff (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "elect-sheriff", votes: [{ from: players[1]._id, for: players[2]._id }] })
@@ -67,7 +70,7 @@ describe("V - Tiny game of 5 players in which because of the early votes, action
});
it("๐ช All vote for the hunter (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[1]._id, for: players[2]._id }] })
@@ -90,7 +93,7 @@ describe("V - Tiny game of 5 players in which because of the early votes, action
});
it("๐ Sheriff delegates to the witch (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate", targets: [{ player: players[4]._id }] })
@@ -99,13 +102,13 @@ describe("V - Tiny game of 5 players in which because of the early votes, action
game = res.body;
expect(game.players[4].attributes).to.deep.include({ name: "sheriff", source: "sheriff" });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(game.players[4]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(game.players[4]._id);
done();
});
});
it("๐ซ Hunter shoots at the witch (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "hunter", action: "shoot", targets: [{ player: players[4]._id }] })
diff --git a/tests/e2e/game/endless-votes.test.js b/tests/e2e/game/endless-votes.test.js
index 6c1d925..79ee272 100644
--- a/tests/e2e/game/endless-votes.test.js
+++ b/tests/e2e/game/endless-votes.test.js
@@ -15,13 +15,16 @@ let players = [
{ name: "Deg", role: "villager" },
{ name: "Dog", role: "villager" },
];
-let token, game;
+let server, token, game;
describe("S - Tiny game of 4 players in which there is no sheriff and a stuttering judge which make a lot of consecutive votes", () => {
before(done => resetDatabase(done));
+ before(done => {
+ server = app.listen(3000, done);
+ });
after(done => resetDatabase(done));
it("๐ค Creates new user (POST /users)", done => {
- chai.request(app)
+ chai.request(server)
.post("/users")
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -31,7 +34,7 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
});
});
it("๐ Logs in successfully (POST /users/login)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/users/login`)
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -42,7 +45,7 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
});
});
it("๐ฒ Creates game with JWT auth (POST /games)", done => {
- chai.request(app)
+ chai.request(server)
.post("/games")
.set({ Authorization: `Bearer ${token}` })
.send({ players, options: { roles: { sheriff: { isEnabled: false } } } })
@@ -53,7 +56,7 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
});
});
it("โ๏ธ Stuttering judge chooses sign (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "stuttering-judge", action: "choose-sign" })
@@ -65,19 +68,19 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
});
it("โ๏ธ Stuttering judge can't request a second vote if action is not 'vote' (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[3]._id }], doesJudgeRequestAnotherVote: true })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION_FOR_JUDGE_REQUEST");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION_FOR_JUDGE_REQUEST");
done();
});
});
it("๐บ Werewolf eats a villager (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[3]._id }] })
@@ -89,7 +92,7 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
});
it("๐ช Tie in votes between werewolf and villager and stuttering judge requests another vote (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -101,7 +104,7 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("need-settlement");
+ expect(game.history[0].play.votesResult).to.equal("need-settlement");
expect(game.players[0].isAlive).to.be.true;
expect(game.players[2].isAlive).to.be.true;
expect(game.waiting).to.be.an("array").lengthOf(2);
@@ -112,7 +115,7 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
});
it("๐ช All vote for villager (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[0]._id, for: players[2]._id }] })
@@ -121,13 +124,13 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
game = res.body;
expect(game.players[2].isAlive).to.be.false;
expect(game.players[2].murdered).to.deep.equals({ by: "all", of: "vote" });
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
done();
});
});
it("๐ช Tie in votes between werewolf and stuttering judge (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -139,7 +142,7 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("need-settlement");
+ expect(game.history[0].play.votesResult).to.equal("need-settlement");
expect(game.players[0].isAlive).to.be.true;
expect(game.players[1].isAlive).to.be.true;
expect(game.waiting).to.be.an("array").lengthOf(1);
@@ -149,7 +152,7 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
});
it("๐ช All vote for stuttering judge (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[0]._id, for: players[1]._id }] })
@@ -158,7 +161,7 @@ describe("S - Tiny game of 4 players in which there is no sheriff and a stutteri
game = res.body;
expect(game.players[1].isAlive).to.be.false;
expect(game.players[1].murdered).to.deep.equals({ by: "all", of: "vote" });
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
done();
});
});
diff --git a/tests/e2e/game/fox-lack-of-neighbors.test.js b/tests/e2e/game/fox-lack-of-neighbors.test.js
new file mode 100644
index 0000000..fff1d4c
--- /dev/null
+++ b/tests/e2e/game/fox-lack-of-neighbors.test.js
@@ -0,0 +1,119 @@
+const { describe, it, before, after } = require("mocha");
+const chai = require("chai");
+const chaiHttp = require("chai-http");
+const app = require("../../../app");
+const Config = require("../../../config");
+const { resetDatabase } = require("../../../src/helpers/functions/Test");
+
+chai.use(chaiHttp);
+const { expect } = chai;
+
+const credentials = { email: "test@test.fr", password: "secret" };
+const originalPlayers = [
+ { name: "Dag", role: "fox" },
+ { name: "Dig", role: "werewolf" },
+ { name: "Deg", role: "villager" },
+ { name: "Dog", role: "villager" },
+];
+let server, token, game, players;
+
+describe("W - Tiny game of 4 players in which fox has less and less neighbors to sniff", () => {
+ before(done => resetDatabase(done));
+ before(done => {
+ server = app.listen(3000, done);
+ });
+ after(done => resetDatabase(done));
+ it("๐ค Creates new user (POST /users)", done => {
+ chai.request(server)
+ .post("/users")
+ .auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
+ .send(credentials)
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ done();
+ });
+ });
+ it("๐ Logs in successfully (POST /users/login)", done => {
+ chai.request(server)
+ .post(`/users/login`)
+ .auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
+ .send(credentials)
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ token = res.body.token;
+ done();
+ });
+ });
+ it("๐ฒ Creates game with JWT auth (POST /games)", done => {
+ chai.request(server)
+ .post("/games")
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ players: originalPlayers, options: { roles: { sheriff: { isEnabled: false } } } })
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ game = res.body;
+ done();
+ });
+ });
+ it("๐ฆ Fox sniffs himself (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "fox", action: "sniff", targets: [{ player: players[0]._id }] })
+ .end((err, res) => {
+ game = res.body;
+ expect(res).to.have.status(200);
+ expect(game.history[0].play.targets).to.exist;
+ expect(game.history[0].play.targets).to.be.lengthOf(3);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[1]._id);
+ expect(game.history[0].play.targets[1].player._id).to.equal(players[0]._id);
+ expect(game.history[0].play.targets[2].player._id).to.equal(players[3]._id);
+ expect(game.players[0].attributes).to.not.exist;
+ done();
+ });
+ });
+ it("๐บ Werewolf eats the first villager (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "werewolves", action: "eat", targets: [{ player: players[2]._id }] })
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ game = res.body;
+ done();
+ });
+ });
+ it("๐ช All vote for the second villager (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "all", action: "vote", votes: [{ from: players[0]._id, for: players[3]._id }] })
+ .end((err, res) => {
+ expect(res).to.have.status(200);
+ game = res.body;
+ expect(game.players[3].isAlive).to.be.false;
+ expect(game.players[3].murdered).to.deep.equals({ by: "all", of: "vote" });
+ done();
+ });
+ });
+ it("๐ฆ Fox sniffs the werewolf, only two targets are present because there is only two players (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "fox", action: "sniff", targets: [{ player: players[1]._id }] })
+ .end((err, res) => {
+ game = res.body;
+ expect(res).to.have.status(200);
+ expect(game.history[0].play.targets).to.exist;
+ expect(game.history[0].play.targets).to.be.lengthOf(2);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[0]._id);
+ expect(game.history[0].play.targets[1].player._id).to.equal(players[1]._id);
+ expect(game.players[0].attributes).to.not.exist;
+ done();
+ });
+ });
+});
\ No newline at end of file
diff --git a/tests/e2e/game/full-game.test.js b/tests/e2e/game/full-game.test.js
index d74fdbe..d4082d3 100644
--- a/tests/e2e/game/full-game.test.js
+++ b/tests/e2e/game/full-game.test.js
@@ -39,19 +39,25 @@ let players = [
{ name: "Dโฐg", role: "stuttering-judge" },
{ name: "D#g", role: "angel" },
{ name: "Dยฑg", role: "thief" },
+ { name: "Dฮฉg", role: "fox" },
+ { name: "Dโg", role: "rusty-sword-knight" },
+ { name: "Dยฟg", role: "bear-tamer" },
];
let additionalCards = [
{ for: "thief", role: "werewolf" },
{ for: "thief", role: "werewolf" },
];
const options = { roles: { idiot: { doesDieOnAncientDeath: false } } };
-let token, game;
+let server, token, game;
-describe("B - Full game of 28 players with all roles", () => {
+describe("B - Full game of 31 players with all roles", () => {
before(done => resetDatabase(done));
+ before(done => {
+ server = app.listen(3000, done);
+ });
after(done => resetDatabase(done));
it("๐ค Creates new user (POST /users)", done => {
- chai.request(app)
+ chai.request(server)
.post("/users")
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -61,7 +67,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("๐ Logs in successfully (POST /users/login)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/users/login`)
.auth(Config.app.basicAuth.username, Config.app.basicAuth.password)
.send(credentials)
@@ -72,7 +78,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("๐ฒ Creates game with JWT auth (POST /games)", done => {
- chai.request(app)
+ chai.request(server)
.post("/games")
.set({ Authorization: `Bearer ${token}` })
.send({ players, options, additionalCards })
@@ -80,34 +86,54 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
additionalCards = game.additionalCards;
+ expect(game.options.repartition.isHidden).to.be.false;
+ expect(game.options.roles.areRevealedOnDeath).to.be.true;
+ expect(game.options.roles.sheriff.electedAt.turn).to.be.equal(1);
+ expect(game.options.roles.sheriff.electedAt.phase).to.be.equal("night");
+ expect(game.options.roles.bigBadWolf.isPowerlessIfWerewolfDies).to.be.true;
+ expect(game.options.roles.whiteWerewolf.wakingUpInterval).to.be.equal(2);
+ expect(game.options.roles.seer.canSeeRoles).to.be.true;
+ expect(game.options.roles.guard.canProtectTwice).to.be.false;
+ expect(game.options.roles.ancient.livesCountAgainstWerewolves).to.equal(2);
+ expect(game.options.roles.ancient.doesTakeHisRevenge).to.be.true;
+ expect(game.options.roles.fox.isPowerlessIfMissesWerewolf).to.be.true;
+ expect(game.options.roles.bearTamer.doesGrowlIfInfected).to.be.true;
+ expect(game.options.roles.stutteringJudge.voteRequestsCount).to.equal(1);
+ expect(game.options.roles.wildChild.isTransformationRevealed).to.be.false;
+ expect(game.options.roles.dogWolf.isChosenSideRevealed).to.be.false;
+ expect(game.options.roles.thief.mustChooseBetweenWerewolves).to.be.true;
+ expect(game.options.roles.thief.additionalCardsCount).to.be.equal(2);
+ expect(game.options.roles.piedPiper.charmedPeopleCountPerNight).to.equal(2);
+ expect(game.options.roles.piedPiper.isPowerlessIfInfected).to.be.true;
+ expect(game.options.roles.raven.markPenalty).to.be.equal(2);
done();
});
});
it("๐ Can't make a play if game's doesn't belong to user (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${new mongoose.Types.ObjectId()}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "elect-sheriff" })
.end((err, res) => {
expect(res).to.have.status(401);
- expect(res.body.type).to.equals("GAME_DOESNT_BELONG_TO_USER");
+ expect(res.body.type).to.equal("GAME_DOESNT_BELONG_TO_USER");
done();
});
});
it("๐ Can't update game review if its status is `playing` (PATCH /games/:id)", done => {
- chai.request(app)
+ chai.request(server)
.patch(`/games/${game._id}`)
.set({ Authorization: `Bearer ${token}` })
.send({ review: { rating: 3 } })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_REQUEST");
+ expect(res.body.type).to.equal("BAD_REQUEST");
done();
});
});
it("๐ Night falls", done => {
players = game.players;
- expect(game.phase).to.equals("night");
+ expect(game.phase).to.equal("night");
expect(players[0].role.isRevealed).to.be.false;
expect(players[8].role.isRevealed).to.be.true;
done();
@@ -117,52 +143,52 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ช All can't elect sheriff if play's source is not 'all' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "seer", action: "look" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ช All can't elect sheriff if play's action is not 'elect-sheriff' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "look" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ช All can't elect sheriff if votes are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "elect-sheriff" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("VOTES_REQUIRED");
+ expect(res.body.type).to.equal("VOTES_REQUIRED");
done();
});
});
it("๐ช All can't elect sheriff if votes are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "elect-sheriff", votes: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("VOTES_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("VOTES_CANT_BE_EMPTY");
done();
});
});
it("๐ช All can't elect sheriff if one vote has same target and source (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -173,13 +199,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("SAME_VOTE_SOURCE_AND_TARGET");
+ expect(res.body.type).to.equal("SAME_VOTE_SOURCE_AND_TARGET");
done();
});
});
it("๐ช All can't elect sheriff if one vote has an unknown source (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -190,13 +216,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_VOTE");
+ expect(res.body.type).to.equal("CANT_VOTE");
done();
});
});
it("๐ช All can't elect sheriff if one vote has an unknown target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -207,13 +233,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_BE_VOTE_TARGET");
+ expect(res.body.type).to.equal("CANT_BE_VOTE_TARGET");
done();
});
});
it("๐ช All can't elect sheriff if one player votes twice (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -224,13 +250,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_VOTE_MULTIPLE_TIMES");
+ expect(res.body.type).to.equal("CANT_VOTE_MULTIPLE_TIMES");
done();
});
});
it("๐ช All can't elect sheriff if there is a tie in votes (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -241,13 +267,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TIE_IN_VOTES");
+ expect(res.body.type).to.equal("TIE_IN_VOTES");
done();
});
});
it("๐ช All elect the little girl as the sheriff (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -263,11 +289,11 @@ describe("B - Full game of 28 players with all roles", () => {
expect(game.players[7].attributes).to.deep.include({ name: "sheriff", source: "all" });
expect(game.history).to.be.an("array").to.have.lengthOf(1);
expect(game.history[0].play.votes).to.exist;
- expect(game.history[0].play.votes[0].from._id).to.equals(game.players[0]._id);
- expect(game.history[0].play.votes[0].for._id).to.equals(game.players[1]._id);
- expect(game.history[0].play.votesResult).to.equals("election");
+ expect(game.history[0].play.votes[0].from._id).to.equal(game.players[0]._id);
+ expect(game.history[0].play.votes[0].for._id).to.equal(game.players[1]._id);
+ expect(game.history[0].play.votesResult).to.equal("election");
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(game.players[7]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(game.players[7]._id);
expect(game.history[0].play.source.name).to.equal("all");
expect(game.history[0].play.source.players).to.be.an("array").to.have.lengthOf(players.length);
expect(game.history[0].deadPlayers).to.not.exist;
@@ -279,29 +305,29 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ช All can't vote if play's source is not 'all' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "seer", action: "look" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ช All can't vote if play's action is not 'vote' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "look" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ช All vote for one brother (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[0]._id, for: players[13]._id }] })
@@ -310,7 +336,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[13].isAlive).to.be.false;
expect(game.history).to.be.an("array").to.have.lengthOf(2);
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.history[0].deadPlayers).to.be.an("array").lengthOf(1);
expect(game.history[0].deadPlayers[0]._id).to.be.equals(game.players[13]._id);
done();
@@ -321,51 +347,51 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ฆน Thief can't choose card if play's source is not 'thief' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "dog-wolf", action: "choose-card" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ฆน Thief can't choose card if play's action is not 'choose-card' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "thief", action: "shoot" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ฆน Thief can't skip if the two additional cards are from the 'werewolves' side (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "thief", action: "choose-card" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("THIEF_MUST_STEAL");
+ expect(res.body.type).to.equal("THIEF_MUST_STEAL");
done();
});
});
it("๐ฆน Thief can't choose an unknown card (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "thief", action: "choose-card", card: new mongoose.Types.ObjectId() })
.end((err, res) => {
expect(res).to.have.status(404);
- expect(res.body.type).to.equals("CHOSEN_CARD_NOT_FOUND");
+ expect(res.body.type).to.equal("CHOSEN_CARD_NOT_FOUND");
done();
});
});
it("๐ฆน Thief chooses the first werewolf card (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "thief", action: "choose-card", card: additionalCards[0]._id })
@@ -373,8 +399,8 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
additionalCards = game.additionalCards;
- expect(game.players[27].role.current).to.equals("werewolf");
- expect(game.players[27].side.current).to.equals("werewolves");
+ expect(game.players[27].role.current).to.equal("werewolf");
+ expect(game.players[27].side.current).to.equal("werewolves");
expect(game.history[0].play.card).to.deep.equals(additionalCards[0]);
done();
});
@@ -384,53 +410,53 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ Dog-wolf can't choose side if play's source is not 'dog-wolf' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "villager-villager", action: "choose-side" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ Dog-wolf can't choose side if play's action is not 'choose-side' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "dog-wolf", action: "shoot" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ Dog-wolf can't choose side if side is not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "dog-wolf", action: "choose-side" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("DOG_WOLF_MUST_CHOOSE_SIDE");
+ expect(res.body.type).to.equal("DOG_WOLF_MUST_CHOOSE_SIDE");
done();
});
});
it("๐ Dog-wolf chooses `werewolves` side (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "dog-wolf", action: "choose-side", side: "werewolves" })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.players[16].side.original).to.equals("villagers");
- expect(game.players[16].side.current).to.equals("werewolves");
+ expect(game.players[16].side.original).to.equal("villagers");
+ expect(game.players[16].side.current).to.equal("werewolves");
expect(game.history).to.be.an("array").to.have.lengthOf(3);
- expect(game.history[0].play.side).to.equals("werewolves");
+ expect(game.history[0].play.side).to.equal("werewolves");
expect(game.history[0].play.source.name).to.equal("dog-wolf");
expect(game.history[0].play.source.players).to.be.an("array").to.have.lengthOf(1);
- expect(game.history[0].play.source.players[0]._id).to.equals(players[16]._id);
+ expect(game.history[0].play.source.players[0]._id).to.equal(players[16]._id);
done();
});
});
@@ -439,75 +465,75 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐น Cupid can't choose side if action is not 'choose-side' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "cupid", action: "charm", side: "werewolves" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION_FOR_SIDE_CHOICE");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION_FOR_SIDE_CHOICE");
done();
});
});
it("๐น Cupid can't charm if play's source is not 'cupid' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "charm" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐น Cupid can't charm if play's action is not 'charm' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "cupid", action: "shoot" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐น Cupid can't charm if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "cupid", action: "charm" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
it("๐น Cupid can't charm if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "cupid", action: "charm", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
it("๐น Cupid can't charm just one target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "cupid", action: "charm", targets: [{ player: players[0]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐น Cupid can't charm more than two targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -519,12 +545,12 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐น Cupid can't charm unknown targets (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -535,13 +561,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐น Cupid can't charm the same targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -552,13 +578,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NON_UNIQUE_TARGETS");
+ expect(res.body.type).to.equal("NON_UNIQUE_TARGETS");
done();
});
});
it("๐น Cupid can't infect a player (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -569,13 +595,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION_FOR_INFECTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION_FOR_INFECTION");
done();
});
});
it("๐น Cupid can't use life potion on a target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -586,13 +612,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION_FOR_POTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION_FOR_POTION");
done();
});
});
it("๐น Cupid can't choose a card (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -603,13 +629,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION_FOR_CHOSEN_CARD");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION_FOR_CHOSEN_CARD");
done();
});
});
it("๐น Cupid can't use death potion on a target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -620,13 +646,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION_FOR_POTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION_FOR_POTION");
done();
});
});
it("๐น Cupid charms himself and the little girl (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -642,190 +668,261 @@ describe("B - Full game of 28 players with all roles", () => {
expect(game.players[9].attributes).to.deep.include({ name: "in-love", source: "cupid" });
expect(game.history).to.be.an("array").to.have.lengthOf(3);
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[7]._id);
- expect(game.history[0].play.targets[1].player._id).to.equals(players[9]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[7]._id);
+ expect(game.history[0].play.targets[1].player._id).to.equal(players[9]._id);
expect(game.history[0].play.source.name).to.equal("cupid");
expect(game.history[0].play.source.players).to.be.an("array").to.have.lengthOf(1);
- expect(game.history[0].play.source.players[0]._id).to.equals(players[9]._id);
+ expect(game.history[0].play.source.players[0]._id).to.equal(players[9]._id);
done();
});
});
- it("๐ฒ Game is waiting for 'lovers' to 'meet-each-other'", done => {
- expect(game.waiting[0]).to.deep.equals({ for: "lovers", to: "meet-each-other" });
+ it("๐ฒ Game is waiting for 'seer' to 'look'", done => {
+ expect(game.waiting[0]).to.deep.equals({ for: "seer", to: "look" });
done();
});
- it("๐ Lovers can't meet each other if play's source is not 'lovers' (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฎ Seer can't look if play's source is not 'seer' (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "all", action: "meet-each-other" })
+ .send({ source: "all", action: "look" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
- it("๐ Lovers can't meet each other if play's action is not 'meet-each-other' (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฎ Seer can't look if play's action is not 'look' (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "lovers", action: "vote" })
+ .send({ source: "seer", action: "elect-sheriff" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
- it("๐ Lovers meet each other (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฎ Seer can't look if targets are not set (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "lovers", action: "meet-each-other" })
+ .send({ source: "seer", action: "look" })
.end((err, res) => {
- game = res.body;
- expect(res).to.have.status(200);
- expect(game.history).to.be.an("array").to.have.lengthOf(3);
+ expect(res).to.have.status(400);
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
- it("๐ฒ Game is waiting for 'stuttering-judge' to 'choose-sign'", done => {
- expect(game.waiting[0]).to.deep.equals({ for: "stuttering-judge", to: "choose-sign" });
- done();
- });
- it("โ๏ธ Stuttering judge can't choose sign if play's source is not 'stuttering-judge' (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฎ Seer can't look if targets are empty (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "witch", action: "choose-sign" })
+ .send({ source: "seer", action: "look", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
- it("โ๏ธ Stuttering judge can't choose sign if play's action is not 'choose-sign' (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฎ Seer can't look at multiple targets (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "stuttering-judge", action: "vote" })
+ .send({
+ source: "seer", action: "look", targets: [
+ { player: players[0]._id },
+ { player: players[1]._id },
+ ],
+ })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
- it("โ๏ธ Stuttering judge chooses sign (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฎ Seer can't look at unknown target (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "stuttering-judge", action: "choose-sign" })
+ .send({ source: "seer", action: "look", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
- game = res.body;
- expect(res).to.have.status(200);
+ expect(res).to.have.status(400);
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
- it("๐ฒ Game is waiting for 'seer' to 'look'", done => {
- expect(game.waiting[0]).to.deep.equals({ for: "seer", to: "look" });
- done();
- });
- it("๐ฎ Seer can't look if play's source is not 'seer' (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฎ Seer can't look at herself (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "all", action: "look" })
+ .send({ source: "seer", action: "look", targets: [{ player: players[1]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("CANT_LOOK_AT_HERSELF");
done();
});
});
- it("๐ฎ Seer can't look if play's action is not 'look' (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฎ Seer looks at the witch (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "seer", action: "elect-sheriff" })
+ .send({ source: "seer", action: "look", targets: [{ player: players[0]._id }] })
.end((err, res) => {
- expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res).to.have.status(200);
+ game = res.body;
+ expect(game.players[0].attributes).to.deep.include({ name: "seen", source: "seer", remainingPhases: 1 });
+ expect(game.history).to.be.an("array").to.have.lengthOf(3);
+ expect(game.history[0].play.targets).to.exist;
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[0]._id);
done();
});
});
- it("๐ฎ Seer can't look if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฒ Game is waiting for 'fox' to 'sniff'", done => {
+ expect(game.waiting[0]).to.deep.equals({ for: "fox", to: "sniff" });
+ done();
+ });
+ it("๐ฆ Fox can't sniff if play's source is not 'fox' (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "seer", action: "look" })
+ .send({ source: "witch", action: "sniff" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
- it("๐ฎ Seer can't look if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฆ Fox can't sniff if play's action is not 'sniff' (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "seer", action: "look", targets: [] })
+ .send({ source: "fox", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
- it("๐ฎ Seer can't look at multiple targets (POST /games/:id/play)", done => {
+ it("๐ฆ Fox can't sniff at multiple targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
- source: "seer", action: "look", targets: [
+ source: "fox", action: "sniff", targets: [
{ player: players[0]._id },
{ player: players[1]._id },
],
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
- it("๐ฎ Seer can't look at unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ it("๐ฆ Fox can't sniff at unknown target (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "seer", action: "look", targets: [{ player: new mongoose.Types.ObjectId() }] })
+ .send({ source: "fox", action: "sniff", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
- it("๐ฎ Seer can't look at herself (POST /games/:id/play)", done => {
- players = game.players;
- chai.request(app)
+ it("๐ฆ Fox sniffs the werewolf on the fifth position (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "seer", action: "look", targets: [{ player: players[1]._id }] })
+ .send({ source: "fox", action: "sniff", targets: [{ player: players[5]._id }] })
+ .end((err, res) => {
+ game = res.body;
+ expect(res).to.have.status(200);
+ expect(game.history[0].play.targets).to.exist;
+ expect(game.history[0].play.targets).to.be.lengthOf(3);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[6]._id);
+ expect(game.history[0].play.targets[1].player._id).to.equal(players[5]._id);
+ expect(game.history[0].play.targets[2].player._id).to.equal(players[4]._id);
+ expect(game.players[28].attributes).to.not.exist;
+ done();
+ });
+ });
+ it("๐ฒ Game is waiting for 'lovers' to 'meet-each-other'", done => {
+ expect(game.waiting[0]).to.deep.equals({ for: "lovers", to: "meet-each-other" });
+ done();
+ });
+ it("๐ Lovers can't meet each other if play's source is not 'lovers' (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "all", action: "meet-each-other" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_LOOK_AT_HERSELF");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
- it("๐ฎ Seer looks at the witch (POST /games/:id/play)", done => {
- players = game.players;
- chai.request(app)
+ it("๐ Lovers can't meet each other if play's action is not 'meet-each-other' (POST /games/:id/play)", done => {
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "seer", action: "look", targets: [{ player: players[0]._id }] })
+ .send({ source: "lovers", action: "vote" })
+ .end((err, res) => {
+ expect(res).to.have.status(400);
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
+ done();
+ });
+ });
+ it("๐ Lovers meet each other (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "lovers", action: "meet-each-other" })
.end((err, res) => {
- expect(res).to.have.status(200);
game = res.body;
- expect(game.players[0].attributes).to.deep.include({ name: "seen", source: "seer", remainingPhases: 1 });
+ expect(res).to.have.status(200);
expect(game.history).to.be.an("array").to.have.lengthOf(3);
- expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[0]._id);
+ done();
+ });
+ });
+ it("๐ฒ Game is waiting for 'stuttering-judge' to 'choose-sign'", done => {
+ expect(game.waiting[0]).to.deep.equals({ for: "stuttering-judge", to: "choose-sign" });
+ done();
+ });
+ it("โ๏ธ Stuttering judge can't choose sign if play's source is not 'stuttering-judge' (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "witch", action: "choose-sign" })
+ .end((err, res) => {
+ expect(res).to.have.status(400);
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
+ done();
+ });
+ });
+ it("โ๏ธ Stuttering judge can't choose sign if play's action is not 'choose-sign' (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "stuttering-judge", action: "vote" })
+ .end((err, res) => {
+ expect(res).to.have.status(400);
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
+ done();
+ });
+ });
+ it("โ๏ธ Stuttering judge chooses sign (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "stuttering-judge", action: "choose-sign" })
+ .end((err, res) => {
+ game = res.body;
+ expect(res).to.have.status(200);
done();
});
});
@@ -834,29 +931,29 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ญ The two sisters can't meet each other if play's source is not 'two-sisters' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "lovers", action: "meet-each-other" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ญ The two sisters can't meet each other if play's action is not 'meet-each-other' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "two-sisters", action: "use-potion" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ญ The two sisters meet each other (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "two-sisters", action: "meet-each-other" })
@@ -871,29 +968,29 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐จโ๐จโ๐ฆ The three brothers can't meet each other if play's source is not 'three-brothers' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "meet-each-other" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐จโ๐จโ๐ฆ The three brothers can't meet each other if play's action is not 'meet-each-other' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "three-brothers", action: "delegate" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐จโ๐จโ๐ฆ The three brothers meet each other (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "three-brothers", action: "meet-each-other" })
@@ -908,52 +1005,52 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ Wild child can't choose model if play's source is not 'wild-child' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "little-girl", action: "choose-model" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ Wild child can't choose model if play's action is not 'choose-model' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "wild-child", action: "use-potion" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ Wild child can't choose model if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "wild-child", action: "choose-model" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
it("๐ Wild child can't choose model if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "wild-child", action: "choose-model", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
it("๐ Wild child can't choose multiple models (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -964,36 +1061,36 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐ Wild child can't choose an unknown model (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "wild-child", action: "choose-model", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ Wild child can't choose himself as a model (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "wild-child", action: "choose-model", targets: [{ player: players[15]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("WILD_CHILD_CANT_CHOOSE_HIMSELF");
+ expect(res.body.type).to.equal("WILD_CHILD_CANT_CHOOSE_HIMSELF");
done();
});
});
it("๐ Wild child chooses the werewolf as a model (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "wild-child", action: "choose-model", targets: [{ player: players[5]._id }] })
@@ -1002,7 +1099,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[5].attributes).to.deep.include({ name: "worshiped", source: "wild-child" });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[5]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[5]._id);
done();
});
});
@@ -1011,30 +1108,30 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ชถ Raven can't mark if play's source is not 'raven' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "villager", action: "mark" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ชถ Raven can't mark if play's action is not 'mark' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "use-potion" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ชถ Raven can't mark multiple targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1045,24 +1142,24 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐ชถ Raven can't mark an unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ชถ Raven marks the villager (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark", targets: [{ player: players[6]._id }] })
@@ -1071,7 +1168,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[6].attributes).to.deep.include({ name: "raven-marked", source: "raven", remainingPhases: 2 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[6]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[6]._id);
done();
});
});
@@ -1080,52 +1177,52 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ก Guard can't protect if play's source is not 'guard' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "protect" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ก Guard can't protect if play's action is not 'protect' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "vote" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ก Guard can't protect if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
it("๐ก Guard can't protect if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
it("๐ก Guard can't protect multiple targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1136,24 +1233,24 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐ก Guard can't protect an unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ก Guard protects the werewolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[5]._id }] })
@@ -1162,7 +1259,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[5].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[5]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[5]._id);
done();
});
});
@@ -1171,52 +1268,52 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐บ Werewolves can't eat if play's source is not 'werewolves' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "seer", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐บ Werewolves can't eat if play's action is not 'eat' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "shoot" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐บ Werewolves can't eat if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
it("๐บ Werewolves can't eat if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
it("๐บ Werewolves can't eat multiple targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1227,48 +1324,48 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐บ Werewolves can't eat an unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐บ Werewolves can't eat another werewolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[5]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_EAT_EACH_OTHER");
+ expect(res.body.type).to.equal("CANT_EAT_EACH_OTHER");
done();
});
});
it("๐บ Werewolves can't eat the dog-wolf because he chose the `werewolves` side (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[16]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_EAT_EACH_OTHER");
+ expect(res.body.type).to.equal("CANT_EAT_EACH_OTHER");
done();
});
});
it("๐บ Werewolves eat the guard (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[2]._id }] })
@@ -1277,7 +1374,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[2].attributes).to.deep.include({ name: "eaten", source: "werewolves", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
done();
});
});
@@ -1286,30 +1383,30 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐บ White werewolf can't eat if play's source is not 'white-werewolf' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "hunter", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐บ White werewolf can't eat if play's action is not 'eat' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "white-werewolf", action: "shoot" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐บ White werewolf can't eat multiple targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1320,48 +1417,48 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐บ White werewolf can't eat an unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "white-werewolf", action: "eat", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐บ White werewolf can't eat a player in the `villagers` side (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "white-werewolf", action: "eat", targets: [{ player: players[0]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("MUST_EAT_WEREWOLF");
+ expect(res.body.type).to.equal("MUST_EAT_WEREWOLF");
done();
});
});
it("๐บ White werewolf can't eat himself (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "white-werewolf", action: "eat", targets: [{ player: players[23]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_EAT_HIMSELF");
+ expect(res.body.type).to.equal("CANT_EAT_HIMSELF");
done();
});
});
it("๐บ White werewolf skips (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "white-werewolf", action: "eat", targets: [] })
@@ -1376,52 +1473,52 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐บ Big bad wolf can't eat if play's source is not 'big-bad-wolf' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "seer", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐บ Big bad wolf can't eat if play's action is not 'eat' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "shoot" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐บ Big bad wolf can't eat if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
it("๐บ Big bad wolf can't eat if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
it("๐บ Big bad wolf can't eat multiple targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1432,72 +1529,72 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐บ Big bad wolf can't eat an unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐บ Big bad wolf can't eat another werewolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [{ player: players[5]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_EAT_EACH_OTHER");
+ expect(res.body.type).to.equal("CANT_EAT_EACH_OTHER");
done();
});
});
it("๐บ Big bad wolf can't eat the dog-wolf because he chose the `werewolves` side (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [{ player: players[16]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_EAT_EACH_OTHER");
+ expect(res.body.type).to.equal("CANT_EAT_EACH_OTHER");
done();
});
});
it("๐บ Big bad wolf can't eat the target chosen by the `werewolves` side (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [{ player: players[2]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGET_ALREADY_EATEN");
+ expect(res.body.type).to.equal("TARGET_ALREADY_EATEN");
done();
});
});
it("๐บ Vile father of wolves can't infect the big bad wolf's target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [{ player: players[14]._id, isInfected: true }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGET_MUST_BE_EATEN_BY_WEREWOLVES");
+ expect(res.body.type).to.equal("TARGET_MUST_BE_EATEN_BY_WEREWOLVES");
done();
});
});
it("๐บ Big bad wolf eats the third brother (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [{ player: players[14]._id }] })
@@ -1506,7 +1603,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[14].attributes).to.deep.include({ name: "eaten", source: "big-bad-wolf", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[14]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[14]._id);
done();
});
});
@@ -1515,65 +1612,65 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ช Witch can't use potion if play's source is not 'witch' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "use-potion" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ช Witch can't use potion if play's action is not 'use-potion' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ช Witch can't use potion if one target have both `hasDrankLifePotion` and `hasDrankDeathPotion` fields set to `true` (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [{ player: players[0]._id, hasDrankLifePotion: true, hasDrankDeathPotion: true }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGET_STRUCTURE");
+ expect(res.body.type).to.equal("BAD_TARGET_STRUCTURE");
done();
});
});
it("๐ช Witch can't use potion on unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [{ player: new mongoose.Types.ObjectId(), hasDrankLifePotion: true }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ช Witch can't use life potion on player not eaten by werewolves (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [{ player: players[0]._id, hasDrankLifePotion: true }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_LIFE_POTION_USE");
+ expect(res.body.type).to.equal("BAD_LIFE_POTION_USE");
done();
});
});
it("๐ช Witch can't use life potion and death potion on same target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1584,13 +1681,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NON_UNIQUE_TARGETS");
+ expect(res.body.type).to.equal("NON_UNIQUE_TARGETS");
done();
});
});
it("๐ช Witch can't use death potion twice (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1601,13 +1698,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("ONLY_ONE_DEATH_POTION");
+ expect(res.body.type).to.equal("ONLY_ONE_DEATH_POTION");
done();
});
});
it("๐ช Witch uses life potion on guard (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [{ player: players[2]._id, hasDrankLifePotion: true }] })
@@ -1615,7 +1712,7 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
expect(game.history[0].play.targets[0].hasDrankLifePotion).to.be.true;
done();
});
@@ -1625,63 +1722,63 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ฃ Pied piper can't charm if play's source is not 'pied-piper' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "cupid", action: "charm" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ฃ Pied piper can't charm if play's action is not 'charm' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "pied-piper", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ฃ Pied piper can't charm if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "pied-piper", action: "charm" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
it("๐ฃ Pied piper can't charm if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "pied-piper", action: "charm", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
it("๐ฃ Pied piper can't charm only one target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "pied-piper", action: "charm", targets: [{ player: players[0]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐ฃ Pied piper can't charm an unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1692,12 +1789,12 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ฃ Pied piper can't charm himself (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1708,12 +1805,12 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_CHARM_HIMSELF");
+ expect(res.body.type).to.equal("CANT_CHARM_HIMSELF");
done();
});
});
it("๐ฃ Pied piper charms third brother and witch (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1735,29 +1832,29 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐บ๏ธ Charmed players can't meet each other if play's source is not 'charmed' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "meet-each-other" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐บ๏ธ Charmed players can't meet each other if play's action is not 'meet-each-other' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "charmed", action: "vote" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐บ๏ธ Charmed players meet each other (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "charmed", action: "meet-each-other" })
@@ -1769,23 +1866,24 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("โ๏ธ Sun is rising", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[6].attributes).to.deep.include({ name: "raven-marked", source: "raven", remainingPhases: 1 });
expect(game.players[2].attributes).to.not.deep.include({ name: "drank-life-potion", source: "witch", remainingPhases: 1 });
expect(game.players[2].attributes).to.not.deep.include({ name: "eaten", source: "werewolves", remainingPhases: 1 });
expect(game.players[14].attributes).to.not.deep.include({ name: "eaten", source: "big-bad-wolf", remainingPhases: 1 });
expect(game.players[5].attributes).to.not.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.players[0].attributes).to.not.deep.include({ name: "seen", source: "seer", remainingPhases: 1 });
+ expect(game.players[30].attributes).to.not.exist;
expect(game.players[2].isAlive).to.be.true;
expect(game.players[2].role.isRevealed).to.be.false;
expect(game.players[14].isAlive).to.be.false;
expect(game.players[14].role.isRevealed).to.be.true;
- expect(game.players[14].murdered.of).to.equals("eat");
- expect(game.players[14].murdered.by).to.equals("big-bad-wolf");
+ expect(game.players[14].murdered.of).to.equal("eat");
+ expect(game.players[14].murdered.by).to.equal("big-bad-wolf");
expect(game.history[0].deadPlayers).to.be.an("array").to.be.lengthOf(1);
- expect(game.history[0].deadPlayers[0]._id).to.equals(players[14]._id);
- expect(game.history[0].deadPlayers[0].murdered.of).to.equals("eat");
- expect(game.history[0].deadPlayers[0].murdered.by).to.equals("big-bad-wolf");
+ expect(game.history[0].deadPlayers[0]._id).to.equal(players[14]._id);
+ expect(game.history[0].deadPlayers[0].murdered.of).to.equal("eat");
+ expect(game.history[0].deadPlayers[0].murdered.by).to.equal("big-bad-wolf");
done();
});
it("๐ฒ Game is waiting for 'all' to 'vote'", done => {
@@ -1793,52 +1891,52 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ช All can't vote if play's source is not 'all' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "seer", action: "vote" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ช All can't vote if play's action is not 'vote' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ช All can't vote if votes are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("VOTES_REQUIRED");
+ expect(res.body.type).to.equal("VOTES_REQUIRED");
done();
});
});
it("๐ช All can't vote if votes are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("VOTES_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("VOTES_CANT_BE_EMPTY");
done();
});
});
it("๐ช All can't vote if one vote has same target and source (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1849,13 +1947,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("SAME_VOTE_SOURCE_AND_TARGET");
+ expect(res.body.type).to.equal("SAME_VOTE_SOURCE_AND_TARGET");
done();
});
});
it("๐ช All can't vote if one vote has an unknown source (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1866,13 +1964,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_VOTE");
+ expect(res.body.type).to.equal("CANT_VOTE");
done();
});
});
it("๐ช All can't vote if one vote has an unknown target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1883,13 +1981,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_BE_VOTE_TARGET");
+ expect(res.body.type).to.equal("CANT_BE_VOTE_TARGET");
done();
});
});
it("๐ช All can't vote if one player votes twice (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1900,13 +1998,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_VOTE_MULTIPLE_TIMES");
+ expect(res.body.type).to.equal("CANT_VOTE_MULTIPLE_TIMES");
done();
});
});
it("๐ช Tie in votes between villager and werewolf [Reason: villager is raven-marked ๐ชถ and little girl, the sheriff, has double vote], then scapegoat dies (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -1927,9 +2025,9 @@ describe("B - Full game of 28 players with all roles", () => {
expect(game.players[5].isAlive).to.be.true;
expect(game.players[6].isAlive).to.be.true;
expect(game.history[0].play.votes).to.exist;
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.history[0].deadPlayers).to.be.an("array").lengthOf(1);
- expect(game.history[0].deadPlayers[0]._id).to.equals(game.players[20]._id);
+ expect(game.history[0].deadPlayers[0]._id).to.equal(game.players[20]._id);
done();
});
});
@@ -1938,51 +2036,51 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ Scapegoat can't ban voting if play's source is not 'scapegoat' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "ban-voting" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ Scapegoat can't ban voting if play's action is not 'settle-votes' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "scapegoat", action: "look" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ Scapegoat can't ban voting an unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "scapegoat", action: "ban-voting", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ Scapegoat can't ban voting a dead target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "scapegoat", action: "ban-voting", targets: [{ player: players[20]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ Scapegoat bans voting the witch, the seer and the guard (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2004,13 +2102,13 @@ describe("B - Full game of 28 players with all roles", () => {
expect(game.players[2].attributes).to.exist;
expect(game.players[2].attributes).to.deep.includes(cantVoteAttribute);
expect(game.history[0].play.source.players).to.be.an("array").lengthOf(1);
- expect(game.history[0].play.source.players[0]._id).to.equals(game.players[20]._id);
+ expect(game.history[0].play.source.players[0]._id).to.equal(game.players[20]._id);
done();
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(2);
+ expect(game.phase).to.equal("night");
+ expect(game.turn).to.equal(2);
done();
});
it("๐ฒ Game is waiting for 'seer' to 'look'", done => {
@@ -2019,19 +2117,19 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ฎ Seer can't look at dead target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "seer", action: "look", targets: [{ player: players[20]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ฎ Seer looks at the guard (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "seer", action: "look", targets: [{ player: players[2]._id }] })
@@ -2040,7 +2138,40 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[2].attributes).to.deep.include({ name: "seen", source: "seer", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
+ done();
+ });
+ });
+ it("๐ฒ Game is waiting for 'fox' to 'sniff'", done => {
+ expect(game.waiting[0]).to.deep.equals({ for: "fox", to: "sniff" });
+ done();
+ });
+ it("๐ฆ Fox can't sniff at a dead target (POST /games/:id/play)", done => {
+ players = game.players;
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "fox", action: "sniff", targets: [{ player: players[20]._id }] })
+ .end((err, res) => {
+ expect(res).to.have.status(400);
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
+ done();
+ });
+ });
+ it("๐ฆ Fox sniffs the ancient on the 19th position which has a werewolf neighbor and a dead neighbor (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "fox", action: "sniff", targets: [{ player: players[19]._id }] })
+ .end((err, res) => {
+ game = res.body;
+ expect(res).to.have.status(200);
+ expect(game.history[0].play.targets).to.exist;
+ expect(game.history[0].play.targets).to.be.lengthOf(3);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[21]._id);
+ expect(game.history[0].play.targets[1].player._id).to.equal(players[19]._id);
+ expect(game.history[0].play.targets[2].player._id).to.equal(players[18]._id);
+ expect(game.players[28].attributes).to.not.exist;
done();
});
});
@@ -2050,18 +2181,18 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ชถ Raven can't mark a dead target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark", targets: [{ player: players[20]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ชถ Raven skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark" })
@@ -2078,31 +2209,31 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ก Guard can't protect a dead target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[20]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ก Guard can't protect the same player twice in a row (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[5]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_PROTECT_TWICE");
+ expect(res.body.type).to.equal("CANT_PROTECT_TWICE");
done();
});
});
it("๐ก Guard protects himself (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[2]._id }] })
@@ -2111,7 +2242,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[2].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
done();
});
});
@@ -2121,19 +2252,19 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐บ Werewolves can't eat a dead target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[20]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐บ Werewolves eat the guard (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[2]._id }] })
@@ -2142,7 +2273,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[2].attributes).to.deep.include({ name: "eaten", source: "werewolves", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
done();
});
});
@@ -2152,19 +2283,19 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐บ Big bad wolf can't eat a dead target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [{ player: players[20]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐บ Big bad wolf eats one of the two sisters (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [{ player: players[11]._id }] })
@@ -2173,7 +2304,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[11].attributes).to.deep.include({ name: "eaten", source: "big-bad-wolf", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[11]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[11]._id);
done();
});
});
@@ -2183,31 +2314,31 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ช Witch can't use death potion on dead target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [{ player: players[20]._id, hasDrankDeathPotion: true }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ช Witch can't use life potion twice (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [{ player: players[2]._id, hasDrankLifePotion: true }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("ONLY_ONE_LIFE_POTION");
+ expect(res.body.type).to.equal("ONLY_ONE_LIFE_POTION");
done();
});
});
it("๐ช Witch uses death potion on seer (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [{ player: players[1]._id, hasDrankDeathPotion: true }] })
@@ -2215,13 +2346,13 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[1]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[1]._id);
expect(game.history[0].play.targets[0].hasDrankDeathPotion).to.be.true;
done();
});
});
it("๐ฃ Pied piper can't charm a dead player (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2232,12 +2363,12 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ฃ Pied piper can't charm an already charmed player (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2248,12 +2379,12 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("ALREADY_CHARMED");
+ expect(res.body.type).to.equal("ALREADY_CHARMED");
done();
});
});
it("๐ฃ Pied piper charms seer and guard (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2275,7 +2406,7 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐บ๏ธ Charmed players meet each other (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "charmed", action: "meet-each-other" })
@@ -2286,11 +2417,12 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("โ๏ธ Sun is rising", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[1].attributes).to.not.deep.include({ name: "drank-death-potion", source: "witch", remainingPhases: 1 });
expect(game.players[2].attributes).to.not.deep.include({ name: "seen", source: "seer", remainingPhases: 1 });
expect(game.players[2].attributes).to.not.deep.include({ name: "eaten", source: "werewolves", remainingPhases: 1 });
expect(game.players[2].attributes).to.not.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
+ expect(game.players[30].attributes).to.not.exist;
expect(game.players[1].isAlive).to.be.false;
expect(game.players[1].murdered).to.deep.equals({ by: "witch", of: "use-potion" });
expect(game.players[2].isAlive).to.be.true;
@@ -2310,7 +2442,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ช All can't vote if one vote has a dead source (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2321,13 +2453,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_VOTE");
+ expect(res.body.type).to.equal("CANT_VOTE");
done();
});
});
it("๐ช All can't vote if one vote has a dead target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2338,13 +2470,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_BE_VOTE_TARGET");
+ expect(res.body.type).to.equal("CANT_BE_VOTE_TARGET");
done();
});
});
it("๐ช All can't vote if one voter has the `cant-vote` attribute (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2355,13 +2487,13 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_VOTE");
+ expect(res.body.type).to.equal("CANT_VOTE");
done();
});
});
it("๐ช Tie in votes between villager-villager and pied piper (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2373,7 +2505,7 @@ describe("B - Full game of 28 players with all roles", () => {
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("need-settlement");
+ expect(game.history[0].play.votesResult).to.equal("need-settlement");
expect(game.players[8].isAlive).to.be.true;
expect(game.players[22].isAlive).to.be.true;
done();
@@ -2384,52 +2516,52 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ Sheriff can't settle votes if play's source is not 'sheriff' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "villager", action: "settle-votes" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ Sheriff can't settle votes if play's action is not 'settle-votes' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ Sheriff can't settle votes if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "settle-votes" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
it("๐ Sheriff can't settle votes if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "settle-votes", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
it("๐ Sheriff can't settle votes with multiple targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2440,36 +2572,36 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐ Sheriff can't settle votes with unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "settle-votes", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ Sheriff can't settle votes with player who was not in previous tie in votes (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "settle-votes", targets: [{ player: players[0]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_BE_CHOSEN_AS_TIEBREAKER");
+ expect(res.body.type).to.equal("CANT_BE_CHOSEN_AS_TIEBREAKER");
done();
});
});
it("๐ Sheriff settles votes by choosing pied piper (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "settle-votes", targets: [{ player: players[22]._id }] })
@@ -2481,27 +2613,48 @@ describe("B - Full game of 28 players with all roles", () => {
expect(game.players[22].murdered).to.deep.equals({ by: "sheriff", of: "settle-votes" });
expect(game.history[0].play.targets).to.exist;
expect(game.history[0].deadPlayers).to.be.an("array").to.be.lengthOf(1);
- expect(game.history[0].deadPlayers[0]._id).to.equals(players[22]._id);
+ expect(game.history[0].deadPlayers[0]._id).to.equal(players[22]._id);
expect(game.history[0].deadPlayers[0].murdered).to.deep.equals({ by: "sheriff", of: "settle-votes" });
done();
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(3);
+ expect(game.phase).to.equal("night");
+ expect(game.turn).to.equal(3);
const cantVoteAttribute = { name: "cant-vote", source: "scapegoat", remainingPhases: 1, activeAt: { turn: 2 } };
expect(game.players[0].attributes).to.not.deep.includes(cantVoteAttribute);
expect(game.players[1].attributes).to.not.deep.includes(cantVoteAttribute);
expect(game.players[2].attributes).to.not.deep.includes(cantVoteAttribute);
done();
});
+ it("๐ฒ Game is waiting for 'fox' to 'sniff'", done => {
+ expect(game.waiting[0]).to.deep.equals({ for: "fox", to: "sniff" });
+ done();
+ });
+ it("๐ฆ Fox sniffs the ancient on the 19th position which has a werewolf neighbor and a dead neighbor (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "fox", action: "sniff", targets: [{ player: players[19]._id }] })
+ .end((err, res) => {
+ game = res.body;
+ expect(res).to.have.status(200);
+ expect(game.history[0].play.targets).to.exist;
+ expect(game.history[0].play.targets).to.be.lengthOf(3);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[21]._id);
+ expect(game.history[0].play.targets[1].player._id).to.equal(players[19]._id);
+ expect(game.history[0].play.targets[2].player._id).to.equal(players[18]._id);
+ expect(game.players[28].attributes).to.not.exist;
+ done();
+ });
+ });
it("๐ฒ Game is waiting for 'raven' to 'mark'", done => {
expect(game.waiting[0]).to.deep.equals({ for: "raven", to: "mark" });
done();
});
it("๐ชถ Raven marks the hunter (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark", targets: [{ player: players[4]._id }] })
@@ -2510,7 +2663,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[4].attributes).to.deep.include({ name: "raven-marked", source: "raven", remainingPhases: 2 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[4]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[4]._id);
done();
});
});
@@ -2520,7 +2673,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ก Guard protects the little girl (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[7]._id }] })
@@ -2529,7 +2682,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[7].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[7]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[7]._id);
done();
});
});
@@ -2539,7 +2692,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐บ Werewolves eat the little girl (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[7]._id }] })
@@ -2548,7 +2701,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[7].attributes).to.deep.include({ name: "eaten", source: "werewolves", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[7]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[7]._id);
done();
});
});
@@ -2558,7 +2711,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐บ White werewolf skips (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "white-werewolf", action: "eat" })
@@ -2570,7 +2723,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐บ Big bad wolf eats the angel (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "big-bad-wolf", action: "eat", targets: [{ player: players[26]._id }] })
@@ -2579,7 +2732,7 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[26].attributes).to.deep.include({ name: "eaten", source: "big-bad-wolf", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[26]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[26]._id);
done();
});
});
@@ -2589,18 +2742,18 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ช Witch can't use death potion twice (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [{ player: players[3]._id, hasDrankDeathPotion: true }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("ONLY_ONE_DEATH_POTION");
+ expect(res.body.type).to.equal("ONLY_ONE_DEATH_POTION");
done();
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion" })
@@ -2612,13 +2765,14 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("โ๏ธ Sun is rising, little girl is eaten even if protected by guard and cupid dies from broken heart ๐", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[4].attributes).to.deep.include({ name: "raven-marked", source: "raven", remainingPhases: 1 });
expect(game.players[7].isAlive).to.be.false;
expect(game.players[7].murdered).to.deep.equals({ by: "werewolves", of: "eat" });
expect(game.players[9].isAlive).to.be.false;
expect(game.players[9].murdered).to.deep.equals({ by: "cupid", of: "charm" });
expect(game.players[7].attributes).to.not.deep.include({ name: "eaten", source: "werewolves", remainingPhases: 1 });
+ expect(game.players[30].attributes).to.not.exist;
done();
});
it("๐ฒ Game is waiting for 'sheriff' to 'delegate'", done => {
@@ -2626,52 +2780,52 @@ describe("B - Full game of 28 players with all roles", () => {
done();
});
it("๐ Sheriff can't delegate if play's source is not 'sheriff' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "villager", action: "delegate" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ Sheriff can't delegate if play's action is not 'delegate' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "eat" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ Sheriff can't delegate if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
it("๐ Sheriff can't delegate if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
it("๐ Sheriff can't delegate to multiple targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2682,36 +2836,36 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐ Sheriff can't delegate to unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ Sheriff can't delegate to a dead target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate", targets: [{ player: players[22]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ Sheriff delegates to the hunter (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate", targets: [{ player: players[4]._id }] })
@@ -2721,20 +2875,20 @@ describe("B - Full game of 28 players with all roles", () => {
expect(game.players[0].attributes).to.not.deep.include({ name: "sheriff", source: "all" });
expect(game.players[4].attributes).to.deep.include({ name: "sheriff", source: "sheriff" });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(game.players[4]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(game.players[4]._id);
done();
});
});
it("๐ช All vote for hunter and stuttering judge request another vote (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[3]._id, for: players[4]._id }], doesJudgeRequestAnotherVote: true })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.players[4].isAlive).to.be.false;
expect(game.players[4].murdered).to.deep.equals({ by: "all", of: "vote" });
done();
@@ -2751,7 +2905,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ Sheriff delegates to the raven (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate", targets: [{ player: players[3]._id }] })
@@ -2761,57 +2915,57 @@ describe("B - Full game of 28 players with all roles", () => {
expect(game.players[4].attributes).to.not.deep.include({ name: "sheriff", source: "all" });
expect(game.players[3].attributes).to.deep.include({ name: "sheriff", source: "sheriff" });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(game.players[3]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(game.players[3]._id);
done();
});
});
it("๐ซ Hunter can't shoot if play's source is not 'hunter' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "shoot" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_SOURCE");
+ expect(res.body.type).to.equal("BAD_PLAY_SOURCE");
done();
});
});
it("๐ซ Hunter can't shoot if play's action is not 'shoot' (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "hunter", action: "use-potion" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_PLAY_ACTION");
+ expect(res.body.type).to.equal("BAD_PLAY_ACTION");
done();
});
});
it("๐ซ Hunter can't shoot if targets are not set (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "hunter", action: "shoot" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_REQUIRED");
+ expect(res.body.type).to.equal("TARGETS_REQUIRED");
done();
});
});
it("๐ซ Hunter can't shoot if targets are empty (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "hunter", action: "shoot", targets: [] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("TARGETS_CANT_BE_EMPTY");
+ expect(res.body.type).to.equal("TARGETS_CANT_BE_EMPTY");
done();
});
});
it("๐ซ Hunter can't shoot at multiple targets (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({
@@ -2822,36 +2976,36 @@ describe("B - Full game of 28 players with all roles", () => {
})
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_TARGETS_LENGTH");
+ expect(res.body.type).to.equal("BAD_TARGETS_LENGTH");
done();
});
});
it("๐ซ Hunter can't shoot at an unknown target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "hunter", action: "shoot", targets: [{ player: new mongoose.Types.ObjectId() }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ซ Hunter can't shoot at a dead target (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "hunter", action: "shoot", targets: [{ player: players[22]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐ซ Hunter shoots at the werewolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "hunter", action: "shoot", targets: [{ player: players[5]._id }] })
@@ -2861,13 +3015,13 @@ describe("B - Full game of 28 players with all roles", () => {
expect(game.players[5].isAlive).to.be.false;
expect(game.players[5].murdered).to.deep.equals({ by: "hunter", of: "shoot" });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(game.players[5]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(game.players[5]._id);
done();
});
});
it("๐ Wild child changed his side to `werewolves` because his model (the werewolf) just died", done => {
- expect(game.players[15].side.original).to.equals("villagers");
- expect(game.players[15].side.current).to.equals("werewolves");
+ expect(game.players[15].side.original).to.equal("villagers");
+ expect(game.players[15].side.current).to.equal("werewolves");
done();
});
it("๐ฒ Game is waiting for 'all' to 'vote'", done => {
@@ -2876,86 +3030,99 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("โ๏ธ Stuttering judge can't request another vote if he already requested it (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[3]._id, for: players[4]._id }], doesJudgeRequestAnotherVote: true })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("ONLY_ONE_SECOND_VOTE_REQUEST");
+ expect(res.body.type).to.equal("VOTE_REQUESTS_EXCEEDED");
done();
});
});
it("๐ช All vote for the stuttering judge (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[3]._id, for: players[25]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.players[25].isAlive).to.be.false;
expect(game.players[25].murdered).to.deep.equals({ by: "all", of: "vote" });
done();
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(4);
+ expect(game.phase).to.equal("night");
+ expect(game.turn).to.equal(4);
done();
});
it("๐ฒ Get game with full history (GET /games/:id?history-limit=0)", done => {
- chai.request(app)
+ chai.request(server)
.get(`/games/${game._id}?history-limit=0`)
.set({ Authorization: `Bearer ${token}` })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history.length).to.equals(42);
+ expect(game.history.length).to.equal(45);
done();
});
});
it("๐ Get only full game history (GET /games/:id/history)", done => {
- chai.request(app)
+ chai.request(server)
.get(`/games/${game._id}/history`)
.set({ Authorization: `Bearer ${token}` })
.end((err, res) => {
expect(res).to.have.status(200);
const history = res.body;
- expect(history.length).to.equals(42);
+ expect(history.length).to.equal(45);
done();
});
});
it("๐ Get only witch plays in game history (GET /games/:id/history?play-source=witch)", done => {
- chai.request(app)
+ chai.request(server)
.get(`/games/${game._id}/history?play-source=witch`)
.set({ Authorization: `Bearer ${token}` })
.end((err, res) => {
expect(res).to.have.status(200);
const history = res.body;
- expect(history.length).to.equals(3);
- expect(history[0].play.source.name).to.equals("witch");
- expect(history[1].play.source.name).to.equals("witch");
- expect(history[2].play.source.name).to.equals("witch");
+ expect(history.length).to.equal(3);
+ expect(history[0].play.source.name).to.equal("witch");
+ expect(history[1].play.source.name).to.equal("witch");
+ expect(history[2].play.source.name).to.equal("witch");
done();
});
});
it("๐ Get only choose-side plays in game history (GET /games/:id/history?play-action=choose-side)", done => {
- chai.request(app)
+ chai.request(server)
.get(`/games/${game._id}/history?play-action=choose-side`)
.set({ Authorization: `Bearer ${token}` })
.end((err, res) => {
expect(res).to.have.status(200);
const history = res.body;
- expect(history.length).to.equals(1);
- expect(history[0].play.action).to.equals("choose-side");
+ expect(history.length).to.equal(1);
+ expect(history[0].play.action).to.equal("choose-side");
+ done();
+ });
+ });
+ it("๐ฆ Fox skips (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "fox", action: "sniff", targets: [] })
+ .end((err, res) => {
+ game = res.body;
+ expect(res).to.have.status(200);
+ expect(game.history[0].play.targets).to.not.exist;
+ expect(game.players[28].attributes).to.not.exist;
done();
});
});
it("๐ชถ Raven skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark" })
@@ -2968,7 +3135,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ก Guard protects himself (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[2]._id }] })
@@ -2977,25 +3144,25 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[2].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
done();
});
});
it("๐บ Werewolves can't eat the wild child because he is a fresh new werewolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[15]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_EAT_EACH_OTHER");
+ expect(res.body.type).to.equal("CANT_EAT_EACH_OTHER");
done();
});
});
it("๐บ Werewolves eat the witch, but vile father of wolves infects her before (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[0]._id, isInfected: true }] })
@@ -3003,15 +3170,15 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
expect(game.players[0].attributes).to.not.deep.include({ name: "eaten", source: "werewolves", remainingPhases: 1 });
- expect(game.players[0].side.current).to.equals("werewolves");
+ expect(game.players[0].side.current).to.equal("werewolves");
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[0]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[0]._id);
expect(game.history[0].play.targets[0].isInfected).to.be.true;
done();
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion" })
@@ -3023,44 +3190,61 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("โ๏ธ Sun is rising", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[0].isAlive).to.be.true;
+ expect(game.players[30].attributes).to.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
done();
});
it("โ๏ธ Stuttering judge can't request another vote if he is dead (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[15]._id }], doesJudgeRequestAnotherVote: true })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("STUTTERING_JUDGE_ABSENT");
+ expect(res.body.type).to.equal("STUTTERING_JUDGE_ABSENT");
done();
});
});
it("๐ช All vote for wild child (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[15]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.players[15].isAlive).to.be.false;
expect(game.players[15].murdered).to.deep.equals({ by: "all", of: "vote" });
done();
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(5);
+ expect(game.phase).to.equal("night");
+ expect(game.turn).to.equal(5);
done();
});
+ it("๐ฆ Fox sniffs the witch which is an infected werewolf (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "fox", action: "sniff", targets: [{ player: players[0]._id }] })
+ .end((err, res) => {
+ game = res.body;
+ expect(res).to.have.status(200);
+ expect(game.history[0].play.targets).to.exist;
+ expect(game.history[0].play.targets).to.be.lengthOf(3);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
+ expect(game.history[0].play.targets[1].player._id).to.equal(players[0]._id);
+ expect(game.history[0].play.targets[2].player._id).to.equal(players[30]._id);
+ done();
+ });
+ });
it("๐ชถ Raven skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark" })
@@ -3073,7 +3257,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ก Guard protects a werewolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[24]._id }] })
@@ -3082,25 +3266,25 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[24].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[24]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[24]._id);
done();
});
});
it("๐บ Vile father of wolves can't infect twice (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[10]._id, isInfected: true }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("ONLY_ONE_INFECTION");
+ expect(res.body.type).to.equal("ONLY_ONE_INFECTION");
done();
});
});
it("๐บ Werewolves eat one of the two sisters (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[10]._id }] })
@@ -3108,24 +3292,24 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[10]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[10]._id);
done();
});
});
it("๐บ White werewolf can't eat a dead target (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "white-werewolf", action: "eat", targets: [{ player: players[5]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NOT_TARGETABLE");
+ expect(res.body.type).to.equal("NOT_TARGETABLE");
done();
});
});
it("๐บ White werewolf eats one werewolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "white-werewolf", action: "eat", targets: [{ player: players[24]._id }] })
@@ -3134,12 +3318,12 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[24].attributes).to.deep.include({ name: "eaten", source: "white-werewolf", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[24]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[24]._id);
done();
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [] })
@@ -3151,35 +3335,53 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("โ๏ธ Sun is rising", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[10].isAlive).to.be.false;
expect(game.players[24].attributes).to.not.deep.include({ name: "eaten", source: "white-werewolf", remainingPhases: 1 });
expect(game.players[24].isAlive).to.be.false;
expect(game.players[24].murdered).to.deep.equals({ by: "white-werewolf", of: "eat" });
+ expect(game.players[30].attributes).to.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
done();
});
it("๐ช All vote for vile father of wolves (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[18]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.players[18].isAlive).to.be.false;
expect(game.players[18].murdered).to.deep.equals({ by: "all", of: "vote" });
done();
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(6);
+ expect(game.phase).to.equal("night");
+ expect(game.turn).to.equal(6);
done();
});
+ it("๐ฆ Fox sniffs the player on the 8th position, which has no alive werewolves neighbors and so, fox becomes powerless (POST /games/:id/play)", done => {
+ chai.request(server)
+ .post(`/games/${game._id}/play`)
+ .set({ Authorization: `Bearer ${token}` })
+ .send({ source: "fox", action: "sniff", targets: [{ player: players[8]._id }] })
+ .end((err, res) => {
+ game = res.body;
+ expect(res).to.have.status(200);
+ expect(game.history[0].play.targets).to.exist;
+ expect(game.history[0].play.targets).to.be.lengthOf(3);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[12]._id);
+ expect(game.history[0].play.targets[1].player._id).to.equal(players[8]._id);
+ expect(game.history[0].play.targets[2].player._id).to.equal(players[6]._id);
+ expect(game.players[28].attributes).to.deep.include({ name: "powerless", source: "fox" });
+ done();
+ });
+ });
it("๐ชถ Raven skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark" })
@@ -3192,7 +3394,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ก Guard protects himself (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[2]._id }] })
@@ -3201,25 +3403,25 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[2].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
done();
});
});
it("๐บ Vile father of wolves can't infect because he is dead (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[12]._id, isInfected: true }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("ABSENT_VILE_FATHER_OF_WOLVES");
+ expect(res.body.type).to.equal("ABSENT_VILE_FATHER_OF_WOLVES");
done();
});
});
it("๐บ Werewolves eat the ancient (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[19]._id }] })
@@ -3227,12 +3429,12 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[19]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[19]._id);
done();
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [] })
@@ -3244,34 +3446,35 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("โ๏ธ Sun is rising, ancient is not dead because he has another life", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[19].role.isRevealed).to.be.false;
expect(game.players[19].isAlive).to.be.true;
expect(game.history[0].revealedPlayers).to.not.exist;
+ expect(game.players[30].attributes).to.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
done();
});
it("๐ช All vote for the big bad wolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[17]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.players[17].isAlive).to.be.false;
expect(game.players[17].murdered).to.deep.equals({ by: "all", of: "vote" });
done();
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(7);
+ expect(game.phase).to.equal("night");
+ expect(game.turn).to.equal(7);
done();
});
it("๐ชถ Raven skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark" })
@@ -3284,7 +3487,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ก Guard protects the raven (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[3]._id }] })
@@ -3293,13 +3496,13 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[3].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[3]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[3]._id);
done();
});
});
it("๐บ Werewolves eat the raven but it's protected by the guard (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[3]._id }] })
@@ -3307,12 +3510,12 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[3]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[3]._id);
done();
});
});
it("๐บ White werewolf eats the dog-wolf (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "white-werewolf", action: "eat", targets: [{ player: players[16]._id }] })
@@ -3323,7 +3526,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [] })
@@ -3335,34 +3538,35 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("โ๏ธ Sun is rising", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[3].isAlive).to.be.true;
expect(game.players[16].isAlive).to.be.false;
expect(game.players[16].murdered).to.deep.equals({ by: "white-werewolf", of: "eat" });
+ expect(game.players[30].attributes).to.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
done();
});
it("๐ช All vote for the white werewolf (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[23]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.players[23].isAlive).to.be.false;
expect(game.players[23].murdered).to.deep.equals({ by: "all", of: "vote" });
done();
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(8);
+ expect(game.phase).to.equal("night");
+ expect(game.turn).to.equal(8);
done();
});
it("๐ชถ Raven skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "raven", action: "mark" })
@@ -3375,7 +3579,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ก Guard protects himself (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[2]._id }] })
@@ -3384,13 +3588,13 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[2].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
done();
});
});
it("๐บ Werewolves eat the raven again (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[3]._id }] })
@@ -3398,12 +3602,12 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[3]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[3]._id);
done();
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [] })
@@ -3416,7 +3620,7 @@ describe("B - Full game of 28 players with all roles", () => {
});
it("๐ Sheriff delegates to the idiot (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate", targets: [{ player: players[21]._id }] })
@@ -3426,25 +3630,26 @@ describe("B - Full game of 28 players with all roles", () => {
expect(game.players[3].attributes).to.not.deep.include({ name: "sheriff", source: "all" });
expect(game.players[21].attributes).to.deep.include({ name: "sheriff", source: "sheriff" });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(game.players[21]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(game.players[21]._id);
done();
});
});
it("โ๏ธ Sun is rising", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[3].isAlive).to.be.false;
+ expect(game.players[30].attributes).to.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
done();
});
it("๐ช All vote for the idiot but he doesn't die, only his role is revealed and he can't vote for the rest of the game (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[21]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("no-death");
+ expect(game.history[0].play.votesResult).to.equal("no-death");
expect(game.players[21].role.isRevealed).to.be.true;
expect(game.players[21].attributes).to.deep.include({ name: "cant-vote", source: "all" });
expect(game.players[21].isAlive).to.be.true;
@@ -3452,13 +3657,13 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(9);
+ expect(game.phase).to.equal("night");
+ expect(game.turn).to.equal(9);
done();
});
it("๐ก Guard protects the witch (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[0]._id }] })
@@ -3467,13 +3672,13 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[0].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[0]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[0]._id);
done();
});
});
it("๐บ Werewolves eat the ancient again and will die (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[19]._id }] })
@@ -3481,12 +3686,12 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[19]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[19]._id);
done();
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [] })
@@ -3498,39 +3703,40 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("โ๏ธ Sun is rising, ancient is dead this time and idiot is still alive because of game option", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[19].role.isRevealed).to.be.true;
expect(game.players[19].isAlive).to.be.false;
expect(game.history[0].revealedPlayers).to.exist;
expect(game.history[0].revealedPlayers).to.be.an("array").lengthOf(1);
- expect(game.history[0].revealedPlayers[0]._id).to.equals(players[19]._id);
+ expect(game.history[0].revealedPlayers[0]._id).to.equal(players[19]._id);
expect(game.history[0].deadPlayers).to.exist;
expect(game.history[0].deadPlayers).to.be.an("array").lengthOf(1);
- expect(game.history[0].deadPlayers[0]._id).to.equals(players[19]._id);
+ expect(game.history[0].deadPlayers[0]._id).to.equal(players[19]._id);
+ expect(game.players[30].attributes).to.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
done();
});
it("๐ช All can't vote if the idiot who is banned from votes tries anyway (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[21]._id, for: players[0]._id }] })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("CANT_VOTE");
+ expect(res.body.type).to.equal("CANT_VOTE");
done();
});
});
it("๐ช All vote for the idiot again, which die this time and doesn't delegate his sheriff power because he's an idiot (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[21]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.players[21].isAlive).to.be.false;
expect(game.players[21].murdered).to.deep.equals({ by: "all", of: "vote" });
expect(game.players[21].attributes).to.deep.includes({ name: "sheriff", source: "sheriff" });
@@ -3538,13 +3744,13 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(10);
+ expect(game.phase).to.equal("night");
+ expect(game.turn).to.equal(10);
done();
});
it("๐ก Guard protects himself (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[2]._id }] })
@@ -3553,26 +3759,26 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[2].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
done();
});
});
- it("๐บ Werewolves eat the last brother (POST /games/:id/play)", done => {
+ it("๐บ Werewolves eat the rusty sword knight (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "werewolves", action: "eat", targets: [{ player: players[12]._id }] })
+ .send({ source: "werewolves", action: "eat", targets: [{ player: players[29]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[12]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[29]._id);
done();
});
});
it("๐ช Witch skips (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "witch", action: "use-potion", targets: [] })
@@ -3584,33 +3790,39 @@ describe("B - Full game of 28 players with all roles", () => {
});
});
it("โ๏ธ Sun is rising", done => {
- expect(game.phase).to.equals("day");
- expect(game.players[12].isAlive).to.be.false;
+ expect(game.phase).to.equal("day");
+ expect(game.players[29].isAlive).to.be.false;
+ expect(game.players[30].attributes).to.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
+ expect(game.players[0].attributes).to.deep.include({ name: "contaminated", source: "rusty-sword-knight", remainingPhases: 1 });
done();
});
- it("๐ช All vote for the witch, which joined the werewolf side earlier (POST /games/:id/play)", done => {
+ it("๐ช All vote for the last brother (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
- .send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[0]._id }] })
+ .send({ source: "all", action: "vote", votes: [{ from: players[2]._id, for: players[12]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("death");
+ expect(game.history[0].play.votesResult).to.equal("death");
expect(game.players[0].isAlive).to.be.false;
- expect(game.players[0].murdered).to.deep.equals({ by: "all", of: "vote" });
+ expect(game.players[0].murdered).to.deep.equals({ by: "rusty-sword-knight", of: "disease" });
+ expect(game.players[12].isAlive).to.be.false;
+ expect(game.players[12].murdered).to.deep.equals({ by: "all", of: "vote" });
done();
});
});
it("๐ Night falls", done => {
- expect(game.phase).to.equals("night");
- expect(game.turn).to.equals(11);
+ expect(game.phase).to.equal("night");
+ expect(game.players[12].isAlive).to.be.false;
+ expect(game.players[0].isAlive).to.be.false;
+ expect(game.turn).to.equal(11);
done();
});
it("๐ก Guard protects the thief (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "guard", action: "protect", targets: [{ player: players[27]._id }] })
@@ -3619,13 +3831,13 @@ describe("B - Full game of 28 players with all roles", () => {
game = res.body;
expect(game.players[27].attributes).to.deep.include({ name: "protected", source: "guard", remainingPhases: 1 });
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[27]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[27]._id);
done();
});
});
it("๐บ Werewolves eat the guard (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "werewolves", action: "eat", targets: [{ player: players[2]._id }] })
@@ -3633,96 +3845,82 @@ describe("B - Full game of 28 players with all roles", () => {
expect(res).to.have.status(200);
game = res.body;
expect(game.history[0].play.targets).to.exist;
- expect(game.history[0].play.targets[0].player._id).to.equals(players[2]._id);
+ expect(game.history[0].play.targets[0].player._id).to.equal(players[2]._id);
done();
});
});
it("โ๏ธ Sun is rising", done => {
- expect(game.phase).to.equals("day");
+ expect(game.phase).to.equal("day");
expect(game.players[2].isAlive).to.be.false;
+ expect(game.players[30].attributes).to.not.deep.include({ name: "growls", source: "bear-tamer", remainingPhases: 1 });
done();
});
it("๐ช All vote for the thief, which joined the werewolf side by choosing a werewolf card (POST /games/:id/play)", done => {
players = game.players;
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "all", action: "vote", votes: [{ from: players[6]._id, for: players[27]._id }] })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.history[0].play.votesResult).to.equals("death");
- expect(game.players[0].isAlive).to.be.false;
- expect(game.players[0].murdered).to.deep.equals({ by: "all", of: "vote" });
+ expect(game.history[0].play.votesResult).to.equal("death");
+ expect(game.players[27].isAlive).to.be.false;
+ expect(game.players[27].murdered).to.deep.equals({ by: "all", of: "vote" });
done();
});
});
it("๐ฒ Game is WON by 'villagers'!!", done => {
- expect(game.status).to.equals("done");
- expect(game.won.by).to.equals("villagers");
+ expect(game.status).to.equal("done");
+ expect(game.won.by).to.equal("villagers");
done();
});
it("๐ Can't make a play if game's done (POST /games/:id/play)", done => {
- chai.request(app)
+ chai.request(server)
.post(`/games/${game._id}/play`)
.set({ Authorization: `Bearer ${token}` })
.send({ source: "sheriff", action: "delegate" })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("NO_MORE_PLAY_ALLOWED");
+ expect(res.body.type).to.equal("NO_MORE_PLAY_ALLOWED");
done();
});
});
it("๐ Can't update game review if `rating` is absent (PATCH /games/:id)", done => {
- chai.request(app)
+ chai.request(server)
.patch(`/games/${game._id}`)
.set({ Authorization: `Bearer ${token}` })
.send({ review: { comment: "That was ok.." } })
.end((err, res) => {
expect(res).to.have.status(400);
- expect(res.body.type).to.equals("BAD_REQUEST");
+ expect(res.body.type).to.equal("BAD_REQUEST");
done();
});
});
it("๐ Setting game review of 3.5 stars (PATCH /games/:id)", done => {
- chai.request(app)
+ chai.request(server)
.patch(`/games/${game._id}`)
.set({ Authorization: `Bearer ${token}` })
.send({ review: { rating: 3.5, comment: "That was ok..", dysfunctionFound: true } })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.review.rating).to.equals(3.5);
+ expect(game.review.rating).to.equal(3.5);
expect(game.review.dysfunctionFound).to.be.true;
done();
});
});
it("๐ Can update game review (PATCH /games/:id)", done => {
- chai.request(app)
+ chai.request(server)
.patch(`/games/${game._id}`)
.set({ Authorization: `Bearer ${token}` })
.send({ review: { rating: 3.5, comment: "That was ok..", dysfunctionFound: true } })
.end((err, res) => {
expect(res).to.have.status(200);
game = res.body;
- expect(game.review.rating).to.equals(3.5);
+ expect(game.review.rating).to.equal(3.5);
expect(game.review.dysfunctionFound).to.be.true;
done();
});
});
-});
-
-/*
- * const players = [
- * { name: "0Dig", role: "witch" },
- * { name: "1Doug", role: "seer" },
- * { name: "2Dag", role: "guard" },
- * { name: "3Dug", role: "raven" },
- * { name: "4Dyg", role: "hunter" },
- * { name: "5Deg", role: "werewolf" },
- * { name: "6Dog", role: "villager" },
- * { name: "7Diig", role: "little-girl" },
- * { name: "8Diig", role: "villager-villager" },
- * { name: "9Dรชg", role: "cupid" },
- * ];
- */
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/tests/e2e/game/game-creation.test.js b/tests/e2e/game/game-creation.test.js
index b88d276..6602b5b 100644
--- a/tests/e2e/game/game-creation.test.js
+++ b/tests/e2e/game/game-creation.test.js
@@ -12,12 +12,12 @@ const { expect } = chai;
const credentials = { email: "test@test.fr", password: "secret" };
const credentials2 = { email: "test@test.frbis", password: "secret" };
const players = [
- { name: "