mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-01-08 04:44:25 +00:00
Prototype for websockspec
This commit is contained in:
240
pkg/websocketspec/message.go
Normal file
240
pkg/websocketspec/message.go
Normal file
@@ -0,0 +1,240 @@
|
||||
package websocketspec
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
)
|
||||
|
||||
// MessageType represents the type of WebSocket message
|
||||
type MessageType string
|
||||
|
||||
const (
|
||||
// MessageTypeRequest is a client request message
|
||||
MessageTypeRequest MessageType = "request"
|
||||
// MessageTypeResponse is a server response message
|
||||
MessageTypeResponse MessageType = "response"
|
||||
// MessageTypeNotification is a server-initiated notification
|
||||
MessageTypeNotification MessageType = "notification"
|
||||
// MessageTypeSubscription is a subscription control message
|
||||
MessageTypeSubscription MessageType = "subscription"
|
||||
// MessageTypeError is an error message
|
||||
MessageTypeError MessageType = "error"
|
||||
// MessageTypePing is a keepalive ping message
|
||||
MessageTypePing MessageType = "ping"
|
||||
// MessageTypePong is a keepalive pong response
|
||||
MessageTypePong MessageType = "pong"
|
||||
)
|
||||
|
||||
// OperationType represents the operation to perform
|
||||
type OperationType string
|
||||
|
||||
const (
|
||||
// OperationRead retrieves records
|
||||
OperationRead OperationType = "read"
|
||||
// OperationCreate creates a new record
|
||||
OperationCreate OperationType = "create"
|
||||
// OperationUpdate updates an existing record
|
||||
OperationUpdate OperationType = "update"
|
||||
// OperationDelete deletes a record
|
||||
OperationDelete OperationType = "delete"
|
||||
// OperationSubscribe subscribes to entity changes
|
||||
OperationSubscribe OperationType = "subscribe"
|
||||
// OperationUnsubscribe unsubscribes from entity changes
|
||||
OperationUnsubscribe OperationType = "unsubscribe"
|
||||
// OperationMeta retrieves metadata about an entity
|
||||
OperationMeta OperationType = "meta"
|
||||
)
|
||||
|
||||
// Message represents a WebSocket message
|
||||
type Message struct {
|
||||
// ID is a unique identifier for request/response correlation
|
||||
ID string `json:"id,omitempty"`
|
||||
|
||||
// Type is the message type
|
||||
Type MessageType `json:"type"`
|
||||
|
||||
// Operation is the operation to perform
|
||||
Operation OperationType `json:"operation,omitempty"`
|
||||
|
||||
// Schema is the database schema name
|
||||
Schema string `json:"schema,omitempty"`
|
||||
|
||||
// Entity is the table/model name
|
||||
Entity string `json:"entity,omitempty"`
|
||||
|
||||
// RecordID is the ID for single-record operations (update, delete, read by ID)
|
||||
RecordID string `json:"record_id,omitempty"`
|
||||
|
||||
// Data contains the request/response payload
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
|
||||
// Options contains query options (filters, sorting, pagination, etc.)
|
||||
Options *common.RequestOptions `json:"options,omitempty"`
|
||||
|
||||
// SubscriptionID is the subscription identifier
|
||||
SubscriptionID string `json:"subscription_id,omitempty"`
|
||||
|
||||
// Success indicates if the operation was successful
|
||||
Success bool `json:"success,omitempty"`
|
||||
|
||||
// Error contains error information
|
||||
Error *ErrorInfo `json:"error,omitempty"`
|
||||
|
||||
// Metadata contains additional response metadata
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||
|
||||
// Timestamp is when the message was created
|
||||
Timestamp time.Time `json:"timestamp,omitempty"`
|
||||
}
|
||||
|
||||
// ErrorInfo contains error details
|
||||
type ErrorInfo struct {
|
||||
// Code is the error code
|
||||
Code string `json:"code"`
|
||||
|
||||
// Message is a human-readable error message
|
||||
Message string `json:"message"`
|
||||
|
||||
// Details contains additional error context
|
||||
Details map[string]interface{} `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
// RequestMessage represents a client request
|
||||
type RequestMessage struct {
|
||||
ID string `json:"id"`
|
||||
Type MessageType `json:"type"`
|
||||
Operation OperationType `json:"operation"`
|
||||
Schema string `json:"schema,omitempty"`
|
||||
Entity string `json:"entity"`
|
||||
RecordID string `json:"record_id,omitempty"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
Options *common.RequestOptions `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
// ResponseMessage represents a server response
|
||||
type ResponseMessage struct {
|
||||
ID string `json:"id"`
|
||||
Type MessageType `json:"type"`
|
||||
Success bool `json:"success"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
Error *ErrorInfo `json:"error,omitempty"`
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// NotificationMessage represents a server-initiated notification
|
||||
type NotificationMessage struct {
|
||||
Type MessageType `json:"type"`
|
||||
Operation OperationType `json:"operation"`
|
||||
SubscriptionID string `json:"subscription_id"`
|
||||
Schema string `json:"schema"`
|
||||
Entity string `json:"entity"`
|
||||
Data interface{} `json:"data"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// SubscriptionMessage represents a subscription control message
|
||||
type SubscriptionMessage struct {
|
||||
ID string `json:"id"`
|
||||
Type MessageType `json:"type"`
|
||||
Operation OperationType `json:"operation"` // subscribe or unsubscribe
|
||||
Schema string `json:"schema,omitempty"`
|
||||
Entity string `json:"entity"`
|
||||
Options *common.RequestOptions `json:"options,omitempty"` // Filters for subscription
|
||||
SubscriptionID string `json:"subscription_id,omitempty"` // For unsubscribe
|
||||
}
|
||||
|
||||
// NewRequestMessage creates a new request message
|
||||
func NewRequestMessage(id string, operation OperationType, schema, entity string) *RequestMessage {
|
||||
return &RequestMessage{
|
||||
ID: id,
|
||||
Type: MessageTypeRequest,
|
||||
Operation: operation,
|
||||
Schema: schema,
|
||||
Entity: entity,
|
||||
}
|
||||
}
|
||||
|
||||
// NewResponseMessage creates a new response message
|
||||
func NewResponseMessage(id string, success bool, data interface{}) *ResponseMessage {
|
||||
return &ResponseMessage{
|
||||
ID: id,
|
||||
Type: MessageTypeResponse,
|
||||
Success: success,
|
||||
Data: data,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewErrorResponse creates an error response message
|
||||
func NewErrorResponse(id string, code, message string) *ResponseMessage {
|
||||
return &ResponseMessage{
|
||||
ID: id,
|
||||
Type: MessageTypeResponse,
|
||||
Success: false,
|
||||
Error: &ErrorInfo{
|
||||
Code: code,
|
||||
Message: message,
|
||||
},
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewNotificationMessage creates a new notification message
|
||||
func NewNotificationMessage(subscriptionID string, operation OperationType, schema, entity string, data interface{}) *NotificationMessage {
|
||||
return &NotificationMessage{
|
||||
Type: MessageTypeNotification,
|
||||
Operation: operation,
|
||||
SubscriptionID: subscriptionID,
|
||||
Schema: schema,
|
||||
Entity: entity,
|
||||
Data: data,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
// ParseMessage parses a JSON message into a Message struct
|
||||
func ParseMessage(data []byte) (*Message, error) {
|
||||
var msg Message
|
||||
if err := json.Unmarshal(data, &msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
// ToJSON converts a message to JSON bytes
|
||||
func (m *Message) ToJSON() ([]byte, error) {
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
// ToJSON converts a response message to JSON bytes
|
||||
func (r *ResponseMessage) ToJSON() ([]byte, error) {
|
||||
return json.Marshal(r)
|
||||
}
|
||||
|
||||
// ToJSON converts a notification message to JSON bytes
|
||||
func (n *NotificationMessage) ToJSON() ([]byte, error) {
|
||||
return json.Marshal(n)
|
||||
}
|
||||
|
||||
// IsValid checks if a message is valid
|
||||
func (m *Message) IsValid() bool {
|
||||
// Type must be set
|
||||
if m.Type == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Request messages must have an ID, operation, and entity
|
||||
if m.Type == MessageTypeRequest {
|
||||
return m.ID != "" && m.Operation != "" && m.Entity != ""
|
||||
}
|
||||
|
||||
// Subscription messages must have an ID and operation
|
||||
if m.Type == MessageTypeSubscription {
|
||||
return m.ID != "" && m.Operation != ""
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user