Socket.IO / Real-Time Events / Auction System

Baraka Socket Server

Complete integration guide for the real-time auction socket server. Covers all client-emitted events, server-emitted events, payload shapes, database models, and connection flow.

⚡ Socket.IO ● NestJS WebSocketGateway 🔒 JWT Auth on Connection 🔔 Room-Based Broadcasting
🔍
Overview

How the socket layer fits into the Baraka system

The Baraka socket server powers all real-time features in the live auction flow. It is built with NestJS + Socket.IO and uses MySQL via Prisma ORM for persistence. Every auction runs inside a dedicated Socket.IO room (auction_{'{'}auctionId{'}'}), so events are scoped to participants.

Transport
Socket.IO (WebSocket + HTTP long-polling)
CORS Policy
All origins allowed (*)
CORS Methods
GET, POST
Room Naming
auction_{'{'}auctionId{'}'}
Authentication on Socket
JWT access token (verified on connect)
Database ORM
Prisma (MySQL)
🔒
Authentication: Every connection is validated in handleConnection. The server verifies the JWT access token and stores userId on client.data. Event handlers read client.data.userId directly — do not pass userId in event payloads. Connections with a missing or invalid token are immediately disconnected.
🔗
Connection

How to establish a Socket.IO connection from the frontend

Base URL (development)
ws://localhost:3000
Namespace
/ (default, no custom namespace)
JavaScript / TypeScript — Connect with JWT
// Install: npm install socket.io-client
import { io } from 'socket.io-client';

const accessToken = '<YOUR_ACCESS_TOKEN>';  // from POST /auth/otp or /auth/refresh

// Option 1 — recommended: pass via auth.token
const socket = io('http://<SERVER_URL>', {
  auth: { token: accessToken },
  transports: ['websocket'],
  reconnection: true,
  reconnectionAttempts: 5,
});

// Option 2 — Authorization header
// const socket = io('http://<SERVER_URL>', {
//   extraHeaders: { authorization: `Bearer ${accessToken}` },
// });

socket.on('connect', () => {
  console.log('Connected:', socket.id);
});

socket.on('disconnect', () => {
  console.log('Disconnected');
});

// Handle connection-level auth failures
socket.on('error', ({ message }) => {
  // 'No token provided' | 'Invalid or expired token'
  console.error('Auth error:', message);
});
The server verifies the token in handleConnection. On success, userId is stored server-side on client.data and used for all subsequent events automatically. On disconnect, the client is removed from all auction rooms and viewer counts are updated.
If no token is provided, or if the token is invalid or expired, the server emits error with the message "No token provided" or "Invalid or expired token" and immediately disconnects the client. Obtain a fresh token via POST /auth/refresh and reconnect.
🎊
Typical Auction Flow

Step-by-step sequence for a live auction session

1
Auction owner emits startLiveAuction → server sets isLive = true, broadcasts auctionStarted to all
2
Owner emits changeCuurentProduct to set the first product, price, and minimum bid → room receives auction_change_product
3
Viewers emit joinAuction → each client joins room auction_{'{'}auctionId{'}'}, room receives userCountUpdate
4
Participants emit placeBid → all room members receive newBid with the updated bids list
5
Participants emit comment → all room members receive newComment with full comments list
6
Owner emits awardingAuction with winning product & weight → room receives auctionEnded with winner details, bids & comments are cleared
7
Owner repeats step 2–6 for next products until done, then emits endAuction → room receives auctionFinished
!
At any point owner can emit cancelAuction → room receives auctionCanceled
Client → Server Events

Events your frontend emits to the socket server

EMIT startLiveAuction 🔒 Owner Only Go live with an auction

Sets the auction's isLive flag to true in the database. Broadcasts auctionStarted to all connected clients (not just room members). Must be called before anyone can join.

Payload
FieldTypeRequiredDescription
auctionIdnumberyesID of the auction to start
Example
socket.emit('startLiveAuction', {
  auctionId: 42,
});  // userId resolved from JWT token
On success, all clients (globally) receive auctionStarted with the updated Auction object. On failure, only the emitting client receives error.
EMIT joinAuction Enter an auction room

Checks that the auction is live, adds the client to the Socket.IO room auction_{'{'}auctionId{'}'}, and increments the user count. If the auction is not live yet, an error is sent back.

Payload
FieldTypeRequiredDescription
auctionIdnumberyesAuction to join
Example
socket.emit('joinAuction', {
  auctionId: 42,
});
If isLive === false, the server emits an error back: "Auction has not started yet."
EMIT leaveAuction Exit an auction room

Removes the client from the room and decrements the viewer count. Also triggers automatically on socket disconnect.

Payload
FieldTypeRequiredDescription
auctionIdnumberyesAuction to leave
Example
socket.emit('leaveAuction', {
  auctionId: 42,
});
EMIT broadCasterLeave 🔒 Owner Only Broadcaster exits the stream

Notifies the room that the broadcaster (auction owner) has left the live video stream. The server validates ownership before broadcasting.

Payload
FieldTypeRequiredDescription
auctionIdnumberyesAuction ID
Example
socket.emit('broadCasterLeave', {
  auctionId: 42,
});  // ownership verified via JWT userId
EMIT comment Post a comment in the auction

Persists a new comment to the database and broadcasts the updated comment list to all room members.

Payload
FieldTypeRequiredDescription
auctionIdnumberyesAuction this comment belongs to
commentstringyesThe comment text
Example
socket.emit('comment', {
  auctionId: 42,
  comment:   'Great item! Starting the bidding.',
});  // userId resolved from JWT token
EMIT placeBid Place a bid on the current product

Validates the bid amount against the last bid, persists it to Auction_bids, and broadcasts the updated bid list to the room.

Payload
FieldTypeRequiredDescription
auctionIdnumberyesTarget auction
amountnumberyesBid amount. Must be strictly greater than the last bid.
Example
socket.emit('placeBid', {
  auctionId: 42,
  amount:    1500,
});  // userId resolved from JWT token
If amount <= lastBid, the server returns: "Bid must be higher than the current bid (X)"
EMIT cancelAuction 🔒 Owner Only Cancel a live auction

Sets isCanceled = true and isLive = false. Notifies all room members.

Payload
FieldTypeRequiredDescription
auctionIdnumberyesAuction to cancel
Example
socket.emit('cancelAuction', {
  auctionId: 42,
});  // ownership verified via JWT userId
EMIT endAuction 🔒 Owner Only Mark auction as ended (no winner)

Sets isEnded = true and isLive = false. Used to close the auction session without awarding. For awarding a winner use awardingAuction.

Payload
FieldTypeRequiredDescription
auctionIdnumberyesAuction to end
Example
socket.emit('endAuction', {
  auctionId: 42,
});  // ownership verified via JWT userId
EMIT awardingAuction 🔒 Owner Only Award a product to the highest bidder

Finds the highest bid for the current product, creates a winnings record, clears all bids & comments for the auction, then resets the current product fields back to empty. Broadcasts the result to the room.

Payload
FieldTypeRequiredDescription
auctionIdnumberyesAuction ID
productstringyesName/description of the product being awarded
weightstringyesWeight of the product (stored in winnings)
Example
socket.emit('awardingAuction', {
  auctionId: 42,
  product:   'Gold Ring – 18K',
  weight:    '5.2g',
});  // ownership verified via JWT userId
After awarding, bids and comments are deleted from the database to prepare for the next product round. The auction itself stays live — use changeCuurentProduct to move to the next product.
EMIT changeCuurentProduct 🔒 Owner Only Set the active product & pricing

Updates the auction's current_product, bidPrice, minBidPrice, and actualPrice in the database, then broadcasts the new state to all room members.

Note the typo in the event name: changeCuurentProduct (double u). Match this exactly.
Payload
FieldTypeRequiredDescription
auctionIdnumberyesAuction ID
productstringyesProduct name / description
minBidPricenumberyesMinimum accepted bid amount
bidPricenumberyesStarting/current bid price
actualPricenumberyesActual market price of the product
Example
socket.emit('changeCuurentProduct', {
  auctionId:   42,
  product:     'Silver Necklace – 925',
  minBidPrice: 800,
  bidPrice:    1000,
  actualPrice: 1400,
});
Server → Client Events

Events the server emits that your frontend must listen for

LISTEN auctionStarted Broadcast to ALL clients

Emitted globally (not room-scoped) when an auction goes live. Use this to update the auction list UI for all users.

Response Payload — Auction object
FieldTypeDescription
idnumberAuction primary key
titlestringAuction title
isLivebooleanWill be true
All other Auction model fields (see Database Models section)
Listen Example
socket.on('auctionStarted', (auction) => {
  console.log('Auction is now live!', auction);
  // Update your auction list UI
});
LISTEN userCountUpdate Emitted to auction room

Triggered whenever a user joins, leaves, or disconnects from an auction room. Show live viewer count.

Response Payload
FieldTypeDescription
auctionIdnumberWhich auction this count belongs to
userCountnumberCurrent number of connected viewers
Listen Example
socket.on('userCountUpdate', ({ auctionId, userCount }) => {
  console.log(`Viewers in auction ${auctionId}: ${userCount}`);
});
LISTEN newComment Emitted to auction room

Fired after a comment is successfully persisted. Returns both the new comment object and the full ordered comment list.

Response Payload
FieldTypeDescription
newCommentAuction_comments & { user }The newly created comment with the user relation included
comments(Auction_comments & { user })[]All comments for this auction ordered by createdAt ASC
newComment fields
FieldTypeDescription
idnumberComment ID
auction_idnumberParent auction ID
user_idnumberUser who commented
commentstringComment text
createdAtDateTimeTimestamp
userusersFull user object (see users model)
Listen Example
socket.on('newComment', ({ newComment, comments }) => {
  // Append newComment to chat, or replace entire list
  setComments(comments);
});
LISTEN newBid Emitted to auction room

Fired after a bid is validated and persisted. Returns the new bid and the full bids list sorted newest-first.

Response Payload
FieldTypeDescription
newBidAuction_bids & { user }The newly placed bid with user relation
auctionBids(Auction_bids & { user })[]All bids for this auction ordered createdAt DESC (newest first)
newBid fields
FieldTypeDescription
idnumberBid ID
auction_idnumberParent auction
user_idnumberBidder
bidnumberBid amount
createdAtDateTimeWhen bid was placed
userusersFull user object
Listen Example
socket.on('newBid', ({ newBid, auctionBids }) => {
  console.log(`New bid: ${newBid.bid} by ${newBid.user.name}`);
  setBids(auctionBids);
});
LISTEN auctionCanceled Emitted to auction room

The auction was canceled by the owner. Redirect or dismiss the live screen.

Response Payload
FieldTypeDescription
auctionIdnumberThe canceled auction
messagestring"The auction has been canceled."
Listen Example
socket.on('auctionCanceled', ({ auctionId, message }) => {
  showAlert(message);
  navigate('/auctions');
});
LISTEN auctionFinished Emitted to auction room

The auction was closed normally via endAuction (without awarding). No winner is declared.

Response Payload
FieldTypeDescription
auctionIdnumberThe finished auction
messagestring"The auction has been ended."
Listen Example
socket.on('auctionFinished', ({ auctionId, message }) => {
  showAlert(message);
});
LISTEN auctionEnded Emitted to auction room

A product round was awarded via awardingAuction. Contains the winning bid, winning user, and the reset auction state. Bids & comments are already cleared at this point.

Response Payload
FieldTypeDescription
auctionAuction & { Auction_bids, Auction_comments }Updated auction object with empty bids and comments arrays
winningBidAuction_bids & { user } | nullThe highest bid record. null if no bids were placed.
winningUserusers | nullFull user record of the winner. null if no bids.
Listen Example
socket.on('auctionEnded', ({ auction, winningBid, winningUser }) => {
  if (winningUser) {
    console.log(`Winner: ${winningUser.name} with bid ${winningBid.bid}`);
  } else {
    console.log('No bids placed.');
  }
  // Reset bids and comments UI
});
LISTEN auction_change_product Emitted to auction room

Notifies room members that the active product has changed. Update the product display and reset bid input accordingly.

Response Payload
FieldTypeDescription
productstringNew current_product value
bidPricenumberStarting bid price
minBidPricenumberMinimum acceptable bid
actualPricenumberActual market price
Listen Example
socket.on('auction_change_product', (data) => {
  setCurrentProduct(data.product);
  setMinBid(data.minBidPrice);
  setStartingBid(data.bidPrice);
  setActualPrice(data.actualPrice);
});
LISTEN broadCasterLeft Emitted to auction room

The auction owner has left the live video stream. Show a "Broadcaster disconnected" message to viewers.

Response Payload
FieldTypeDescription
auctionIdnumberThe affected auction
Listen Example
socket.on('broadCasterLeft', ({ auctionId }) => {
  showBanner('The broadcaster has left. Please wait...');
});
ERROR error Emitted to the sender only

Sent privately to the client that triggered an invalid action. Always listen for this to surface server-side validation errors in your UI.

Response Payload
FieldTypeDescription
messagestringHuman-readable error reason
Common Error Messages
TriggerError Message
connectionNo token provided
connectionInvalid or expired token
startLiveAuctionUnauthorized or Auction not found
joinAuctionAuction has not started yet.
placeBidBid must be higher than the current bid (X)
placeBidAuction not found! / User not found!
cancelAuctionYou only cancel live auctions!
cancelAuctionAuction is already canceled
cancelAuctionYou are not allowed to cancel this auction!
endAuctionAuction is already Ended
awardingAuctionYou are not allowed to end the auction
awardingAuction / changeCuurentProductAuction could not be ended.
Listen Example
socket.on('error', ({ message }) => {
  showToast(message, 'error');
});
📊
Database Models

Prisma schema definitions for all models involved in socket responses

When socket responses include nested objects (e.g. user inside a bid), these are Prisma relation includes — the full model is returned. Models below reflect the exact database schema.
Auction Main auction record
FieldTypeNotes
idPKIntAuto-increment
titleString
descriptionString
typeAuctionTypeLive | Open
current_productString?Active product name
product_descriptionString?
actualPriceIntMarket price
minBidPriceIntMinimum bid allowed
bidPriceIntStarting bid price
quantityIntDefault 1
expiryDateDateTime
startDateDateTime?
isLiveBooleanDefault false
isExpiredBooleanDefault false
isCanceledBooleanDefault false
isEndedBooleanDefault false
image_urlStringCover image
user_idFKInt?→ users.id (creator)
winning_user_idFKInt?→ users.id (winner)
category_idFKInt→ categories.id
createdAtDateTimeAuto now
updatedAtDateTimeAuto update
Auction_bidsAuction_bids[]Relation — included in auctionEnded
Auction_commentsAuction_comments[]Relation — included in auctionEnded
users User profile
FieldTypeNotes
idPKIntAuto-increment
nameStringDisplay name
typeuserTypeNormal | Expert
category_idFKInt?→ categories.id
numberStringPhone number
otpCodeString?Temporary OTP
createdAtDateTime
updatedAtDateTime
Auction_bids Individual bid record
FieldTypeNotes
idPKIntAuto-increment
auction_idFKInt→ Auction.id (cascade delete)
user_idFKInt→ users.id (cascade delete)
bidIntBid amount
createdAtDateTime
updatedAtDateTime
userusersRelation — always included in socket response
⚠ All bids are deleted after awardingAuction
Auction_comments Chat message
FieldTypeNotes
idPKIntAuto-increment
auction_idFKInt→ Auction.id (cascade delete)
user_idFKInt→ users.id (cascade delete)
commentStringComment text
createdAtDateTime
updatedAtDateTime
userusersRelation — always included in socket response
⚠ All comments are deleted after awardingAuction
winnings Award record (persisted)
FieldTypeNotes
idPKIntAuto-increment
user_idFKInt→ users.id (winner)
auction_idFKInt?→ Auction.id
productStringProduct name awarded
priceIntWinning bid amount
weightString?Product weight
soldBooleanDefault false
createdAtDateTime
updatedAtDateTime
✓ Created on every successful awardingAuction call
categories Auction category
FieldTypeNotes
idPKInt
nameStringCategory name
pic_urlStringCategory image
createdAtDateTime
updatedAtDateTime
Enums
AuctionType
Live  |  Open
userType
Normal  |  Expert
Baraka Socket Server Documentation  ·  Generated from src/modules/socket/socket.gateway.ts & prisma/schema.prisma  ·  Keep this file in sync when the gateway changes.