Data Flow
Relevant source files
The following files were used as context for generating this wiki page:- packages/client/src/index.ts
- packages/core/src/api/controllers/messageController.ts
- packages/core/src/connectors/IConnector.ts
- packages/core/src/types/apiTypes.ts
- packages/core/src/api/middleware/authMiddleware.ts
- packages/core/src/index.ts
- packages/core/prisma/schema.prisma
- packages/core/src/types/dataModels.ts
The data flow for sending a message in MessageJS is designed to be asynchronous and secure. It involves the client-side SDK making a request to the core backend API, which then validates the request, queues the message for processing, and hands it off to a specific connector for delivery to a third-party service like WhatsApp or Telegram. This architecture ensures that no sensitive credentials are ever exposed to the frontend.
The high-level flow follows the path: Client SDK → API Gateway → Connector Router → Third-party APIs. The API immediately responds to the client after queuing the message, while the actual sending happens in the background.
Sources: README.md, QUICK_START.md
Message Sending Sequence
The following diagram illustrates the end-to-end sequence for sending a message, from the initial SDK call to the final asynchronous response.
This diagram shows the synchronous part of the flow, where the client receives a 202 Accepted response, confirming the message is queued. The subsequent processing with the third-party connector happens asynchronously on the backend.
Sources: packages/client/src/index.ts:98-124, packages/core/src/api/controllers/messageController.ts:22-75, packages/core/src/api/middleware/authMiddleware.ts:15-73
Client SDK Initiation
The process begins in the user's application with the @messagejs/client SDK. The developer calls the sendMessage method with the required parameters.
Sources: packages/client/src/index.ts:98-104
sendMessage Parameters
The sendMessage method accepts a SendParams object with the following structure:
| Parameter | Type | Description |
|---|---|---|
connectorId | string | The ID of the connector configuration to use. |
templateId | string | The ID of the message template to use. |
to | string | The recipient's identifier (e.g., E.164 phone number). |
variables | Record<string, any> | Key-value pairs to replace variables in the template. |
metadata | Record<string, any> (optional) | Optional data to associate with the message for logging. |
Sources: packages/client/src/index.ts:36-58
The SDK then constructs an HTTP POST request to the /api/v1/messages endpoint of the backend, including the API key in the Authorization header as a Bearer token.
Sources: packages/client/src/index.ts:108-115
API Request Lifecycle
When the request reaches the @messagejs/core backend, it goes through several stages of processing.
This flowchart shows the request path through the Express server, highlighting the synchronous response and the subsequent asynchronous processing.
Sources: packages/core/src/index.ts:36-37, packages/core/src/api/middleware/authMiddleware.ts, packages/core/src/api/controllers/messageController.ts
1. Authentication Middleware
Before the request reaches the main controller, the validateApiKey middleware intercepts it.
- It checks for an
Authorizationheader with the formatBearer <api_key>. - It validates the provided API key. (The current implementation uses a mock key for validation).
- If the key is valid, it attaches an
apiKeyobject containing theidandprojectIdto the ExpressRequestobject for use in downstream controllers. - If the key is invalid or missing, it terminates the request with a
401 Unauthorizedor403 Forbiddenresponse.
Sources: packages/core/src/api/middleware/authMiddleware.ts:15-73, packages/core/src/types/security.ts:16-22
2. Message Controller
The sendMessage controller in messageController.ts is responsible for the core logic:
- It receives the validated request, which includes the
SendMessageRequestbody. - It is designed to create a new
Messagelog entry in the database with a status of'queued'. - It generates a unique
messageId. - It returns a
202 AcceptedHTTP status with aSendMessageSuccessResponsepayload, confirming that the message has been accepted for processing.
The controller's comments outline a more robust future implementation, including input validation, fetching entities from the database, decrypting credentials, and pushing a job to an async queue.
Sources: packages/core/src/api/controllers/messageController.ts:22-75
Core Data Structures
The data flow relies on a set of well-defined data structures for API communication and database persistence.
API Data Contracts
The primary API contract for this flow is defined in apiTypes.ts.
Request Body: SendMessageRequest
// packages/core/src/types/apiTypes.ts:38-45
export interface SendMessageRequest {
connectorId: string;
templateId: string;
to: string;
variables: Record<string, any>;
metadata?: Record<string, any>;
}
Success Response: SendMessageSuccessResponse
// packages/core/src/types/apiTypes.ts:48-54
export interface SendMessageSuccessResponse {
messageId: string;
status: "queued";
externalId: string | null;
details: string;
}
Sources: packages/core/src/types/apiTypes.ts:38-54
Database Schema
The schema.prisma file defines the database models that store all state. The MessageLog (aliased as Message in dataModels.ts) is central to tracking a message's lifecycle.
The diagram below shows the relationships between the key models involved in sending a message.
A Message record is created with a status of queued and is linked to the Project, APIKey, and Connector used for the request.
Sources: packages/core/prisma/schema.prisma, packages/core/src/types/dataModels.ts
Connector Abstraction (IConnector)
The IConnector interface is the cornerstone of MessageJS's pluggable architecture. It defines a standard contract that every messaging provider (e.g., WhatsApp, Twilio) must implement. This allows the core system to handle message sending in a provider-agnostic way.
This diagram shows the IConnector interface and its relationship with the data structures it uses for sending messages. The sendMessage method is the key function called by the asynchronous job worker to dispatch the message to the third-party API.