Files
harmony-back/spec.md
julien vdb 0bb06e0e2d
All checks were successful
Build release Docker image / Build Docker Images (push) Successful in 7m23s
0.12.18 : add create message, conversation
2026-01-16 13:23:27 +01:00

6.3 KiB

Technical Specification: Chat Messaging Feature

Task Complexity: Medium

Rationale

  • Involves creating relationships between 3 entities (ChatMessage, ChatConversation, ChatConversationMember)
  • Handles two conversation types with different logic (direct vs group)
  • Requires user authentication and transactional data creation
  • Some edge cases (creating conversation before message, handling members, etc.)

Technical Context

  • Language: TypeScript
  • Framework: Strapi 4
  • Database: Relational DB (presumed based on Strapi structure)
  • Existing patterns: Core controller pattern with custom methods (see post.ts)

Current State

Completed

  • Schema definitions for ChatMessage, ChatConversation, ChatConversationMember
  • Service layer structure in place (core service factories)
  • Basic controller scaffolding

Missing

  • Custom controller methods for creating messages and conversations
  • Business logic for handling conversation creation workflow

Data Model Overview

ChatConversation

  • title: Optional conversation name
  • isGroup: Boolean (true if 3+ users, false if 2 users)
  • creator: Relation to user
  • messages: OneToMany relation to ChatMessage
  • users: OneToMany relation to user

ChatConversationMember

  • user: OneToOne relation to user
  • conversation: OneToOne relation to ChatConversation
  • role: Enum (member, admin, owner)
  • joinedAt: DateTime
  • lastReadAt: DateTime

ChatMessage

  • sender: OneToOne relation to user
  • content: String (required)
  • isEdited: Boolean (default: false)
  • deletedAt: DateTime
  • Note: No back-relation to ChatConversation (by design)

Implementation Approach

1. Controller Methods

createMessage(ctx)

  • Purpose: Create a message in a conversation
  • Parameters:
    • conversationId (query/body): ID of target conversation (null if creating new conversation)
    • content (body): Message content (required)
    • recipientIds (body, optional): User IDs for new conversation
  • Logic:
    • Get authenticated user from ctx.state.user.id
    • If conversationId is null/undefined:
      • Call createConversation() with recipientIds and authenticated user
      • Use returned conversation ID
    • Create ChatMessage with:
      • sender: authenticated user ID
      • content: message content
    • Add message to ChatConversation.messages relation
    • Return created message with populated relations

createConversation(ctx)

  • Purpose: Create a new conversation with one or more users
  • Parameters:
    • userIds (body): Array of user IDs to add to conversation
    • title (body, optional): Conversation title (for groups)
  • Logic:
    • Get authenticated user from ctx.state.user.id
    • Merge authenticated user into conversation members
    • Remove duplicates from user list
    • Determine if group: isGroup = totalUsers > 2
    • Create ChatConversation:
      • isGroup: boolean
      • creator: authenticated user ID
      • title: title (optional, for groups)
    • Create ChatConversationMember records for each user:
      • user: user ID
      • conversation: created conversation ID
      • role: "owner" for creator, "member" for others
      • joinedAt: current timestamp
    • Return created conversation

2. Integration Points

  • Authentication: Use ctx.state.user?.id (follows existing pattern in post.ts)
  • Database queries: Use strapi.db.query() pattern (established in codebase)
  • Error handling: Follow Strapi context methods (ctx.badRequest(), ctx.unauthorized())

3. Files to Modify

  • /Users/julien/projets/dev/harmony/harmony-back/src/api/chat-message/controllers/chat-message.ts — Add createMessage() and helper logic
  • /Users/julien/projets/dev/harmony/harmony-back/src/api/chat-conversation/controllers/chat-conversation.ts — Add createConversation()

4. No Schema Changes Required

  • ChatMessage schema is intentionally unidirectional (no back-relation)
  • All necessary relations already defined in ChatConversation and ChatConversationMember

Verification Approach

  1. Type checking: Run Strapi build or npm run build
  2. Linting: Run project linting command (TBD - will check package.json)
  3. Manual testing:
    • Create message in existing conversation
    • Create message with null conversationId (should create conversation first)
    • Create conversation with 2 users (direct message)
    • Create conversation with 3+ users (group chat)
    • Verify isGroup flag is set correctly
    • Verify ChatConversationMember records are created with correct roles

Implementation Decisions (Confirmed)

  1. User validation: Validate recipient user IDs exist before creating conversation
  2. API routing: createMessage belongs to chat-message controller
  3. Permission checks: Verify user is member of conversation before sending message

Detailed Implementation Plan

Task 1: Implement createConversation in chat-conversation controller

  • Validate all recipient user IDs exist in database
  • Add authenticated user to members list
  • Determine isGroup based on total user count (>2 = group)
  • Create ChatConversation record with creator and title
  • Create ChatConversationMember records for all users with appropriate roles
  • Return created conversation with populated members

Task 2: Implement createMessage in chat-message controller

  • Validate authenticated user exists
  • If conversationId is null: call service method to create conversation with recipientIds
  • If conversationId is provided:
    • Verify conversation exists
    • Verify user is member of conversation (permission check)
  • Validate message content (required, non-empty)
  • Create ChatMessage with sender and content
  • Add message to conversation.messages relation
  • Return created message with populated sender relation

Task 3: Add helper service methods in chat-conversation service

  • createConversationWithMembers(): Centralized logic for creating conversation + members
  • Used by both direct createConversation controller and createMessage

Task 4: Add helper service methods in chat-message service

  • createMessageInConversation(): Centralized logic for creating and linking message

Task 5: Verification

  • Build and type-check the project
  • Run linting
  • Verify error handling for edge cases