- Node.Js
- Typescript
- Serverless
- Java Runtime Engine (JRE) version 6.x or newer
- (Important) Add a
config
file under.aws
folder (C:\Users\USERNAME\.aws\config
for Windows and~/.aws/config
for Unix-based systems)
To start local dev, simply run:
yarn run start_local
OR
Follow the steps below for detailed step breakdown:
- Install dependencies
# Cleanup auto-generated folders
yarn run dev:cleanup
# Install dependencies
yarn run install_dep
-
Remember to uncomment the code for local dev in serverless.yml
-
(Important) Increase max space size for Node (otherwise, webpack may not work in your local machine)
export NODE_OPTIONS="--max-old-space-size=8192"
- Install dynamodb local (this will create a folder called
.dynamodb
in the project root directory) and start serverless and dynamodb locally
yarn run dev:run
- Test Connection here by entering the websocket url (e.g.
ws://localhost:3001
)
For more details on local dev, see the following links
- To invoke lambda function locally see invoke-local
- Add profile and credentials to .aws/credentials and ./aws/config file OR use aws-vault (Recommended):
aws-vault add gamblingkings-sls
- Deploy or remove AWS resources
Note:--no-session
flag seems to be required。 See this bug for more details
To deploy:
aws-vault exec <PROFILE_NAME> --no-session -- sls deploy
To remove:
aws-vault exec <PROFILE_NAME> --no-session -- sls remove
To start a production build and deploy to AWS:
yarn start
SET_USERNAME
{
"action": "SET_USERNAME",
"payload": {
"username": "new user"
}
}
GET_ALL_USERS
{
"action": "GET_ALL_USERS"
}
CREATE_GAME
{
"action": "CREATE_GAME",
"payload": {
"game": {
"gameName": "Chow Yun-fat,the Mahjong King",
"gameType": "Mahjong",
"gameVersion": "Japanese"
}
}
}
GET_ALL_GAMES
{
"action": "GET_ALL_GAMES"
}
SEND_MESSAGE
{
"action": "SEND_MESSAGE",
"payload": {
"username": "test user",
"message": "custom message to all users"
}
}
JOIN_GAME
{
"action": "JOIN_GAME",
"payload": {
"gameId": "5938902b-2e2c-4da8-b900-5cdfbba8f10c"
}
}
LEAVE_GAME
{
"action": "LEAVE_GAME",
"payload": {
"gameId": "5938902b-2e2c-4da8-b900-5cdfbba8f10c"
}
}
START_GAME
{
"action": "START_GAME",
"payload": {
"gameId": "5938902b-2e2c-4da8-b900-5cdfbba8f10c"
}
}
GAME_PAGE_LOAD
{
"action": "GAME_PAGE_LOAD",
"payload": {
"gameId": "5938902b-2e2c-4da8-b900-5cdfbba8f10c"
}
}
DRAW_TILE
{
"action": "DRAW_TILE",
"payload": {
"gameId": "5938902b-2e2c-4da8-b900-5cdfbba8f10c"
}
}
PLAY_TILE
{
"action": "PLAY_TILE",
"payload": {
"gameId": "5938902b-2e2c-4da8-b900-5cdfbba8f10c",
"tile": "1_DOT"
}
}
PLAYED_TILE_INTERACTION
{
"action": "PLAYED_TILE_INTERACTION",
"payload": {
"gameId": "5938902b-2e2c-4da8-b900-5cdfbba8f10c",
"playedTiles": ["1_DOT", "1_DOT", "1_DOT"],
"meldType": "TRIPLET",
"skipInteraction": false
}
}
WIN_ROUND
{
"action": "WIN_ROUND",
"payload": {
"gameId": "5938902b-2e2c-4da8-b900-5cdfbba8f10c",
"handPointResults": {
"totalPoints": 3,
"handPoints": 3,
"extraPoints": 0,
"windPoints": 0,
"dragonPoints": 0,
"flowerPoints": 0,
"hands": [
{
"points": 3,
"name": "ALL_TRIPLET"
}
],
"tiles": [
{
"type": "DOT",
"value": 1
},
{
"type": "DOT",
"value": 1
},
{
"type": "DOT",
"value": 2
},
{
"type": "DOT",
"value": 2
},
{
"type": "DOT",
"value": 2
},
{
"type": "DOT",
"value": 3
},
{
"type": "DOT",
"value": 3
},
{
"type": "DOT",
"value": 3
},
{
"type": "DOT",
"value": 4
},
{
"type": "DOT",
"value": 4
},
{
"type": "DOT",
"value": 4
},
{
"type": "CHARACTER",
"value": 7
},
{
"type": "CHARACTER",
"value": 7
},
{
"type": "CHARACTER",
"value": 7
}
],
"wind": "EAST",
"bonusTiles": [],
"flower": 1,
"concealedPoint": 0
}
}
}
SELF_PLAY_TILE
{
"action": "SELF_PLAY_TILE",
"payload": {
"gameId": "5938902b-2e2c-4da8-b900-5cdfbba8f10c",
"playedTile": "1_Dot",
"isQuad": false,
"alreadyMeld": false
}
}
connect
x 4: Four users connect to websocketCREATE_GAME
: One user creates a gameJOIN_GAME
x 3: Three other users join the game created by the hostSTART_GAME
: Starts the game if there are four users in the gameGAME_PAGE_LOAD
x 4: Wait until assets are loaded on the frontend for all four usersGAME_START
: Officially starts the game if gameLoadedCount for the game in the Games table is 4DRAW_TILE
: Draw one tile and send it to a user in the gameLEAVE_GAME
: To remove user from the Games table if user disconnects or manually leave a game. Note: if the user leaving the game is the game host, the game will be deletedPLAY_TILE
: Send a played tile to all users in the gamePLAYED_TILE_INTERACTION
* 3: Interact with a played tile to make a meld (Consecutive, Triplet, or Quad), and the backend will decide who can take this tile based on meld priority. If all three other users decide not to take the tile, the tile can be skipped and not taken by anyoneSELF_PLAY_TILE
: To play bonus tiles automatically at game start or during the gameWIN_ROUND
: To win a game, update wind/dealer, and start a new game and distribute tiles to each user
- Jest framework is used for testing
- jest-dynalite is used to run test with a mock DynamoDB instance
- jest-extended is used to add additional matchers to Jest's default ones
- jest.config.js
- jest-dynalite-config.js
- global.d.ts: for ide or editor to recognize jest-extended library
- See test
- Refactor and optimize addUserToGame call to DynamoDB
- Refactor and optimize removeUserFromGame call to DynamoDB
See this article to know more about how to optimize build time using typescript, serverless, webpack, and eslint