AuctionHouse WebSocket Gateway v1.0 ยท live

socket.io (NestJS) ยท namespace: / (default) origin: * (CORS configured) realtime auction management
managers & developers events + Prisma models
Connection & lifecycle
How clients connect, disconnect, and join auction rooms.
connect / disconnect system
The gateway automatically tracks connections. No special event needed โ€“ socket.id is used internally.
๐Ÿ“ฅ on connection (client receives)
connected ยท socket.id assigned
๐Ÿ“ค on disconnection
client removed from all auction rooms ยท userCountUpdate emitted to room
Rooms & user count
Auction rooms are named auction_{auctionId}. Presence tracked via auctionUsers Map.
userCountUpdate (server emit)
{
    auctionId: number,      // auction identifier
    userCount: number       // current connected clients in that room
}
Broadcast to the specific auction room whenever a user joins/leaves (including disconnect).
client โ†’ server events
startLiveAuction broadcaster only
client โ†’ server
{
    "auctionId": number,
    "userId": number
}
Initiates auction (sets isLive=true). Only the auction creator (user_id) can start.
server emits: auctionStarted (full Auction object) to ALL clients (broadcast).
// Auction (prisma model) โ€“ all fields except relations
{
    id: number, title: string, description: string, type: "Live" | ...,
    current_product?: string | null, product_description?: string | null,
    actualPrice: number, minBidPrice: number, quantity: number,
    bidPrice: number, expiryDate: string (ISO), startDate?: string | null,
    isLive: boolean, isExpired: boolean, isCanceled: boolean, isEnded: boolean,
    image_url: string, user_id?: number | null, winning_user_id?: number | null,
    category_id: number, createdAt: string, updatedAt: string
}
may emit error { message: string } if unauthorized/not found.
joinAuction any user
{
    "auctionId": number,
    "userId": number
}
Client joins the room auction_{auctionId} only if auction is live. Updates user count. (TODO: emit old comments โ€“ placeholder).
server emits: userCountUpdate to room (see above), plus possible error if auction not live.
leaveAuction
{"auctionId": number, "userId": number}
Leaves room, updates user count โ†’ emits userCountUpdate.
broadCasterLeave
{"auctionId": number, "userId": number}
Called when broadcaster (owner) leaves โ€“ validates ownership via service. If owner, notifies room.
server emits: broadCasterLeft to room:
{ auctionId: number }
comment
{
    "auctionId": number,
    "userId": number,
    "comment": string
}
Stores comment, returns full comment list + the new comment. Included user relation
server emits: newComment to room auction_{auctionId} with payload:
{
    newComment: {
        id: number,
        auction_id: number,
        user_id: number,
        comment: string,
        createdAt: string,
        user: {           // users model (selected fields)
            id: number,
            name: string,
            type: string,
            number: string,
            // ... other user fields (excluding sensitive)
        }
    },
    comments: [ /* array of same comment structure, ascending createdAt */ ]
}
placeBid
{
    "auctionId": number,
    "userId": number,
    "amount": number
}
Places a bid. Validates > last bid amount. Returns new bid + all bids (with user).
server emits: newBid to room:
{
    newBid: {
        id: number,
        auction_id: number,
        user_id: number,
        bid: number,
        createdAt: string,
        user: { id: number, name: string, type: string, number: string }
    },
    auctionBids: [ /* array of all bids (same structure) descending createdAt */ ]
}
cancelAuction
{"auctionId": number, "userId": number}
Only owner can cancel a live auction. Sets isCanceled=true, isLive=false.
server emits: auctionCanceled to room:
{
    auctionId: number,
    message: "The auction has been canceled."
}
endAuction
{"auctionId": number, "userId": number}
Soft end: sets isEnded=true, isLive=false. (Different from awarding).
server emits: auctionFinished to room:
{
    auctionId: number,
    message: "The auction has been ended."
}
awardingAuction
{
    "auctionId": number,
    "userId": number,
    "product": string
}
Finalizes auction: picks highest bid, deletes bids/comments, creates winnings record, resets product fields. Returns updated auction + winning bid + winning user.
server emits: auctionEnded
{
    auction: Auction,       // updated Auction (product fields cleared, isLive=false, isEnded likely true)
    winningBid: {
        id: number,
        auction_id: number,
        user_id: number,
        bid: number,
        createdAt: string,
        user: users         // populated
    } | null,
    winningUser: {
        id: number,
        name: string,
        type: string,
        number: string,
        // ... other user fields
    } | null
}
changeCuurentProduct spelling preserved
{
    "auctionId": number,
    "product": string,
    "minBidPrice": number,
    "bidPrice": number,
    "actualPrice": number
}
Allows host to switch current product and set new baseline prices.
server emits: auction_change_product to room:
{
    product: string,          // current_product
    bidPrice: number,
    minBidPrice: number,
    actualPrice: number
}
server โ†’ client events (typed)
event payload shape (with prisma models) target
auctionStarted
Auction (full model)
all clients
error { message: string } emitting client
userCountUpdate { auctionId: number, userCount: number } auction room
broadCasterLeft { auctionId: number } auction room
newComment { newComment: Auction_comments & { user: users }, comments: Array<Auction_comments & { user: users }> } auction room
newBid { newBid: Auction_bids & { user: users }, auctionBids: Array<Auction_bids & { user: users }> } auction room
auctionCanceled { auctionId: number, message: string } auction room
auctionFinished { auctionId: number, message: string } auction room
auctionEnded { auction: Auction, winningBid: (Auction_bids & { user: users }) | null, winningUser: users | null } auction room
auction_change_product { product: string, bidPrice: number, minBidPrice: number, actualPrice: number } auction room
Prisma models reference
Exact shapes based on your schema โ€“ used in server emits.
Auction model
{
    id: number
    title: string
    description: string
    type: AuctionType            // "Live" | ...
    current_product: string | null
    product_description: string | null
    actualPrice: number
    minBidPrice: number
    quantity: number
    bidPrice: number
    expiryDate: DateTime (ISO string)
    startDate: DateTime | null
    isLive: boolean
    isExpired: boolean
    isCanceled: boolean
    isEnded: boolean
    image_url: string
    user_id: number | null
    winning_user_id: number | null
    category_id: number
    createdAt: DateTime
    updatedAt: DateTime
    // relations are usually not included unless explicitly populated (e.g., Auction_comments, Auction_bids, user, etc.)
}
users model
{
    id: number
    name: string
    type: userType               // "Normal" | ...
    category_id: number | null
    number: string
    otpCode: string | null       // usually omitted from emits
    createdAt: DateTime
    updatedAt: DateTime
    // relations: createdAuctions, winningAuctions, comments, bids, winnings, ...
}
Auction_comments model
{
    id: number
    auction_id: number
    user_id: number
    comment: string
    createdAt: DateTime
    // when populated: user (users model)
}
Auction_bids model
{
    id: number
    auction_id: number
    user_id: number
    bid: number
    createdAt: DateTime
    // when populated: user (users model)
}
design notes & typing:
  • All server emits now map directly to your Prisma models: Auction, users, Auction_comments, Auction_bids.
  • Fields like otpCode are excluded from responses by the service (only user object contains safe fields: id, name, type, number).
  • userCountUpdate is a plain object, not stored in DB.
  • When a relation is included (e.g., user inside comment/bid) it contains the full users object without sensitive data.