- 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_URIvariable 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
useLoginhook we callclient.refetchQueriesafter a successful user login, which changes thedatavariable in Auth.tsx (useGetMehook reexecutes the graphql query) and triggers theuseEffecthook that redirects to the Home component -
Feat: when user signup automatically is redirected to Home:
Signup.tsxcomponent callsawait login({ email, password })after a successful signup -
Use
makeVarfrom Apollo Client to mantain authentication state and conditionally render the Header components -
Chat.tsx:- When you call the
useCreateMessagehook (insidehandleCreateMessage), you execute a mutation (CreateMessage) to create a new message. In youruseCreateMessagehook, 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
useMessageCreatedhook performs GraphQL websocket subscription and manually updates the Apollo client cache every time a new message is received. - (Moved to
ChatList.tsx)useGetMessageshook in your Chat component is subscribed to the messages data in the Apollo cache. It retrieves the currentmessagesin 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
latestMessagesend to the chat and received from the websocket connection to automatically display it in theChatListItemas well as theuser.nameof the sender -
ChatList.tsxreact-infinite-scroller, implement infinite scrolling with pagination to fetch more chats. Implement cache policies in apollo client to define the merge behavior of thechatscache field. When you scroll down the Box component, a new query is sent to thechatsresolver to fetch the next batch of chats, its sorted in the mongodb aggregation and returned in the correct order to be consumed in thedatavariable. -
Chat.tsxreact-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 themessagescache 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
