- React UI + Material UI and Apollo Client (cache)
- NestJS + Apollo GraphQL server
- MongoDB as persistence layer, aggregations and pagination
- You need MongoDB running on
mongodb://127.0.0.1:27017/chatter
. Alternatively, you can use MongoDB Atlas and provide the conection string toMONGODB_URI
variable in./chatter-backend/.env
- Start NestJS backend server:
cd ./chatter-backend && nest start
- Start the React application:
yarn start
-
Feat: when user login automatically is redirected to Home -> In
useLogin
hook we callclient.refetchQueries
after a successful user login, which changes thedata
variable in Auth.tsx (useGetMe
hook reexecutes the graphql query) and triggers theuseEffect
hook that redirects to the Home component -
Feat: when user signup automatically is redirected to Home:
Signup.tsx
component callsawait login({ email, password })
after a successful signup -
Use
makeVar
from Apollo Client to mantain authentication state and conditionally render the Header components -
Chat.tsx
:- When you call the
useCreateMessage
hook (insidehandleCreateMessage
), you execute a mutation (CreateMessage
) to create a new message. In youruseCreateMessage
hook, you have an update function that manually updates the Apollo client cache: it reads the current messages from the cache, adds the new message, and writes the updated array back to the cache. - The
useMessageCreated
hook performs GraphQL websocket subscription and manually updates the Apollo client cache every time a new message is received. - (Moved to
ChatList.tsx
)useGetMessages
hook in your Chat component is subscribed to the messages data in the Apollo cache. It retrieves the currentmessages
in the cache automatically when the cache is updated. - React re-renders the Chat component with the new messages array, so the new message appears in the UI immediately—without a page refresh or manual fetch.
- When you call the
-
Update the Apollo Client cache for every
latestMessage
send to the chat and received from the websocket connection to automatically display it in theChatListItem
as well as theuser.name
of the sender -
ChatList.tsx
react-infinite-scroller, implement infinite scrolling with pagination to fetch more chats. Implement cache policies in apollo client to define the merge behavior of thechats
cache field. When you scroll down the Box component, a new query is sent to thechats
resolver to fetch the next batch of chats, its sorted in the mongodb aggregation and returned in the correct order to be consumed in thedata
variable. -
Chat.tsx
react-infinite-scroller, implement reverse infinite scrolling with pagination to fetch more chat messages. Implement cache policies in apollo client to define the merge behavior of themessages
cache field for eachchatId
GraphQL users.resolver.ts
forwards the query to the UsersService
which calls UsersRepository
that extends AbstractEntityRepository
that performs CRUD on MongoDB with mongoose ORM
Create a unique index in the users
collection on the email
field to prevent duplicate emails using database migrations
Strategies are a concept of the passport
library.
Guards are called before the route is called. Guards need to be changed a bit to work with GraphQL, check gql-auth.guard.ts
auth.controller.ts
operates the route /auth/login and uses the LocalAuthGuard
which implements the local strategy, receives email and password, validates user in MongoDB and injects JWT as cookie
GqlAuthGuard
implements the jwt strategy, which extracts the JWT from the request and validates it or throws Unauthorized 401 exception, GqlAuthGuard
is applied to all routes except CreateUser
in graphql resolver
GraphQL subscriptions mantain a persistent websocket connection to keep pushing updates to the UI client, when a user enters a chat it stablishes a websocket connection using the chatId
Published messages to GraphQL are filtered by chatId
and not sent to the sender (userId
) subscription.
ReModel the ChatDocument
MongoDB schema as an aggregation of MessageDocument
and execute MongoDB aggregations in the chats and messages service layers to operate these schemas
Implement /chats/count
and /messages/count
REST endpoints with NestJS controllers
Implement pagination with MongoDB aggregations in chats and messages service layers