use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use yrs::
encoding::read::Error as DecodeError
;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum MessageType {
Sync = 0,
Awareness = 1,
Auth = 2,
QueryAwareness = 3,
SyncReply = 4, Stateless = 5, BroadcastStateless = 6, SyncStatus = 7, Close = 8, }
impl From<u8> for MessageType {
fn from(value: u8) -> Self {
match value {
0 => MessageType::Sync,
1 => MessageType::Awareness,
2 => MessageType::Auth,
3 => MessageType::QueryAwareness,
5 => MessageType::Stateless,
6 => MessageType::BroadcastStateless,
7 => MessageType::SyncStatus,
8 => MessageType::Close,
_ => panic!("Invalid message type: {}", value),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum SyncType {
Step1 = 0,
Step2 = 1,
Update = 2,
}
impl SyncType {
pub fn from_u8(value: u8) -> Result<Self, DecodeError> {
match value {
0 => Ok(SyncType::Step1),
1 => Ok(SyncType::Step2),
2 => Ok(SyncType::Update),
_ => panic!("Invalid sync type: {}", value),
}
}
pub fn from_u64(value: u64) -> Result<Self, DecodeError> {
Self::from_u8(value as u8)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ClientAwareness {
pub client_id: u64,
pub clock: u32,
pub state: Option<serde_json::Value>,
}
#[derive(Debug)]
pub enum SyncMessage<'a> {
Step1 { state_vector: &'a [u8] },
Step2 { update: &'a [u8] },
Update { update: &'a [u8] },
}
impl<'a> SyncMessage<'a> {
pub fn decode(sync_type: SyncType, data: &'a [u8]) -> Result<Self, DecodeError> {
match sync_type {
SyncType::Step1 => Ok(SyncMessage::Step1 { state_vector: data }),
SyncType::Step2 => Ok(SyncMessage::Step2 { update: data }),
SyncType::Update => Ok(SyncMessage::Update { update: data }),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SyncMessageType {
Step1 = 0,
Step2 = 1,
Update = 2,
}
impl From<u8> for SyncMessageType {
fn from(value: u8) -> Self {
match value {
0 => SyncMessageType::Step1,
1 => SyncMessageType::Step2,
2 => SyncMessageType::Update,
_ => panic!("Invalid sync message type: {}", value),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionConfiguration {
pub id: String,
pub is_authenticated: bool,
pub readonly: bool,
pub user_id: Option<String>,
pub socket_id: String,
pub context: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocumentConfiguration {
pub name: String,
pub gc: bool,
}
impl Default for DocumentConfiguration {
fn default() -> Self {
Self {
name: String::new(),
gc: true,
}
}
}
#[derive(Clone)]
pub struct HocuspocusConfiguration {
pub name: Option<String>,
pub timeout: u64,
pub debounce: u64,
pub max_debounce: u64,
pub quiet: bool,
pub extensions: Vec<Arc<dyn Extension>>,
}
impl Default for HocuspocusConfiguration {
fn default() -> Self {
Self {
name: None,
timeout: 30000,
debounce: 2000,
max_debounce: 10000,
quiet: false,
extensions: Vec::new(),
}
}
}
#[async_trait::async_trait]
pub trait Extension: Send + Sync {
async fn on_configure(
&self,
_configuration: &mut HocuspocusConfiguration,
) -> anyhow::Result<()> {
Ok(())
}
async fn on_listen(&self, _port: u16) -> anyhow::Result<()> {
Ok(())
}
async fn on_upgrade(
&self,
_request: &axum::http::Request<axum::body::Body>,
) -> anyhow::Result<()> {
Ok(())
}
async fn on_connect(&self, _data: ConnectEventData) -> anyhow::Result<()> {
Ok(())
}
async fn on_authenticate(
&self,
_data: AuthenticateEventData,
) -> anyhow::Result<serde_json::Value> {
Ok(serde_json::Value::Null)
}
async fn connected(&self, _data: ConnectedEventData) -> anyhow::Result<()> {
Ok(())
}
async fn on_create_document(&self, _data: CreateDocumentEventData) -> anyhow::Result<()> {
Ok(())
}
async fn on_load_document(
&self,
_data: LoadDocumentEventData,
) -> anyhow::Result<Option<Vec<u8>>> {
Ok(None)
}
async fn before_handle_message(
&self,
_data: BeforeHandleMessageEventData,
) -> anyhow::Result<()> {
Ok(())
}
async fn before_broadcast(&self, _data: BeforeBroadcastEventData) -> anyhow::Result<()> {
Ok(())
}
async fn on_change(&self, _data: ChangeEventData) -> anyhow::Result<()> {
Ok(())
}
async fn on_store_document(&self, _data: StoreDocumentEventData) -> anyhow::Result<()> {
Ok(())
}
async fn after_store_document(&self, _data: AfterStoreDocumentEventData) -> anyhow::Result<()> {
Ok(())
}
async fn on_awareness_update(&self, _data: AwarenessUpdateEventData) -> anyhow::Result<()> {
Ok(())
}
async fn before_send_stateless(
&self,
_data: BeforeSendStatelessEventData,
) -> anyhow::Result<()> {
Ok(())
}
async fn before_send_awareness(
&self,
_data: BeforeSendAwarenessEventData,
) -> anyhow::Result<()> {
Ok(())
}
async fn on_disconnect(&self, _data: DisconnectEventData) -> anyhow::Result<()> {
Ok(())
}
async fn on_destroy(&self) -> anyhow::Result<()> {
Ok(())
}
async fn after_unload_document(
&self,
_data: AfterUnloadDocumentEventData,
) -> anyhow::Result<()> {
Ok(())
}
async fn on_stateless(&self, _data: StatelessEventData) -> anyhow::Result<()> {
Ok(())
}
}
#[derive(Clone)]
pub struct ConnectEventData {
pub socket_id: String,
pub connection: ConnectionConfiguration,
pub request_headers: HashMap<String, String>,
pub request_path: String,
}
#[derive(Clone, Debug)]
pub struct AuthenticateEventData {
pub doc_id: String,
pub token: String,
}
#[derive(Clone)]
pub struct ConnectedEventData {
pub socket_id: String,
}
#[derive(Clone)]
pub struct CreateDocumentEventData {
pub document_name: String,
pub socket_id: String,
pub connection: ConnectionConfiguration,
}
#[derive(Clone)]
pub struct LoadDocumentEventData {
pub document_name: String,
pub socket_id: String,
}
#[derive(Clone)]
pub struct BeforeHandleMessageEventData {
pub message: Vec<u8>,
pub socket_id: String,
pub connection: ConnectionConfiguration,
}
#[derive(Clone)]
pub struct BeforeBroadcastEventData {
pub document_name: String,
pub exclude: Vec<String>,
pub message: Vec<u8>,
}
#[derive(Clone)]
pub struct ChangeEventData {
pub document_name: String,
pub socket_id: String,
pub update: Vec<u8>,
}
#[derive(Clone)]
pub struct StoreDocumentEventData {
pub document_name: String,
pub state: Vec<u8>,
}
#[derive(Clone)]
pub struct AfterStoreDocumentEventData {
pub document_name: String,
}
#[derive(Clone)]
pub struct AwarenessUpdateEventData {
pub document_name: String,
pub awareness: Vec<u8>,
pub added: Vec<u64>,
pub updated: Vec<u64>,
pub removed: Vec<u64>,
}
#[derive(Clone)]
pub struct BeforeSendStatelessEventData {
pub document_name: String,
pub socket_id: String,
pub payload: String,
}
#[derive(Clone)]
pub struct BeforeSendAwarenessEventData {
pub document_name: String,
pub socket_id: String,
pub awareness: Vec<u8>,
}
#[derive(Clone)]
pub struct DisconnectEventData {
pub socket_id: String,
}
#[derive(Clone)]
pub struct AfterUnloadDocumentEventData {
pub document_name: String,
}
#[derive(Clone)]
pub struct StatelessEventData {
pub document_name: String,
pub socket_id: String,
pub payload: String,
}
pub type ChannelId = String;
pub type DocumentName = String;
pub type SocketId = String;