mirror of
https://github.com/hexedtech/codemp.git
synced 2024-11-22 15:24:48 +01:00
feat: javascript glue
Co-authored-by: alemi.dev <me@alemi.dev>
This commit is contained in:
parent
f699d2e8fe
commit
754b88fd73
6 changed files with 47 additions and 104 deletions
|
@ -52,6 +52,7 @@ impl AuthWrap {
|
|||
/// will disconnect when dropped
|
||||
/// can be used to interact with server
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "js", napi_derive::napi)]
|
||||
pub struct Client(Arc<ClientInner>);
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -1,27 +1,11 @@
|
|||
use std::sync::Arc;
|
||||
use napi::threadsafe_function::{ErrorStrategy::Fatal, ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode};
|
||||
use napi_derive::napi;
|
||||
use crate::api::TextChange;
|
||||
use crate::ffi::js::JsCodempError;
|
||||
use crate::api::Controller;
|
||||
use crate::prelude::*;
|
||||
|
||||
|
||||
|
||||
impl From<crate::Error> for napi::Error {
|
||||
fn from(value: crate::Error) -> Self {
|
||||
let msg = format!("{value}");
|
||||
match value {
|
||||
crate::Error::Deadlocked => napi::Error::new(napi::Status::WouldDeadlock, msg),
|
||||
_ => napi::Error::new(napi::Status::GenericFailure, msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
impl CodempBufferController {
|
||||
|
||||
|
||||
#[napi(ts_args_type = "fun: (event: JsTextChange) => void")]
|
||||
pub fn callback(&self, fun: napi::JsFunction) -> napi::Result<()>{
|
||||
let tsfn : ThreadsafeFunction<crate::api::TextChange, Fatal> =
|
||||
|
@ -47,14 +31,13 @@ impl CodempBufferController {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
#[napi(js_name = "recv")]
|
||||
pub async fn jsrecv(&self) -> napi::Result<TextChange> {
|
||||
pub async fn js_recv(&self) -> napi::Result<TextChange> {
|
||||
Ok(self.recv().await?.into())
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn send(&self, op: TextChange) -> napi::Result<()> {
|
||||
#[napi(js_name = "send")]
|
||||
pub fn js_send(&self, op: TextChange) -> napi::Result<()> {
|
||||
Ok(self.send(op)?)
|
||||
}
|
||||
}
|
|
@ -1,43 +1,37 @@
|
|||
use napi_derive::napi;
|
||||
use crate::ffi::js::JsCodempError;
|
||||
|
||||
#[napi]
|
||||
/// main codemp client session
|
||||
pub struct JsCodempClient(tokio::sync::RwLock<crate::Client>);
|
||||
use crate::prelude::*;
|
||||
|
||||
#[napi]
|
||||
/// connect to codemp servers and return a client session
|
||||
pub async fn connect(addr: Option<String>) -> napi::Result<JsCodempClient>{
|
||||
let client = crate::Client::new(addr.as_deref().unwrap_or("http://codemp.alemi.dev:50053"))
|
||||
pub async fn connect(addr: Option<String>, username: String, password: String) -> napi::Result<CodempClient>{
|
||||
let client = crate::Client::new(addr.as_deref().unwrap_or("http://codemp.alemi.dev:50053"), username, password)
|
||||
.await?;
|
||||
|
||||
Ok(JsCodempClient(tokio::sync::RwLock::new(client)))
|
||||
}
|
||||
|
||||
#[napi]
|
||||
impl JsCodempClient {
|
||||
#[napi]
|
||||
/// login against AuthService with provided credentials, optionally requesting access to a workspace
|
||||
pub async fn login(&self, username: String, password: String, workspace_id: Option<String>) -> napi::Result<()> {
|
||||
self.0.read().await.login(username, password, workspace_id).await?;
|
||||
Ok(())
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
impl CodempClient {
|
||||
#[napi(js_name = "join_workspace")]
|
||||
/// join workspace with given id (will start its cursor controller)
|
||||
pub async fn join_workspace(&self, workspace: String) -> napi::Result<JsWorkspace> {
|
||||
Ok(JsWorkspace::from(self.0.write().await.join_workspace(&workspace).await?))
|
||||
pub async fn js_join_workspace(&self, workspace: String) -> napi::Result<CodempWorkspace> {
|
||||
Ok(self.join_workspace(workspace).await?)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
#[napi(js_name = "get_workspace")]
|
||||
/// get workspace with given id, if it exists
|
||||
pub async fn get_workspace(&self, workspace: String) -> Option<JsWorkspace> {
|
||||
self.0.read().await.get_workspace(&workspace).map(|w| JsWorkspace::from(w))
|
||||
pub fn js_get_workspace(&self, workspace: String) -> Option<CodempWorkspace> {
|
||||
self.get_workspace(&workspace)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
#[napi(js_name = "user_id")]
|
||||
/// return current sessions's user id
|
||||
pub async fn user_id(&self) -> String {
|
||||
self.0.read().await.user_id().to_string()
|
||||
pub fn js_user_id(&self) -> String {
|
||||
self.user_id().to_string()
|
||||
}
|
||||
|
||||
#[napi(js_name = "active_workspaces")]
|
||||
pub fn js_active_workspaces(&self) -> Vec<String> {
|
||||
self.active_workspaces()
|
||||
}
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
use std::sync::Arc;
|
||||
use napi_derive::napi;
|
||||
use uuid::Uuid;
|
||||
use napi::threadsafe_function::{ThreadsafeFunction, ThreadSafeCallContext, ThreadsafeFunctionCallMode, ErrorStrategy};
|
||||
use crate::api::Controller;
|
||||
use crate::prelude::*;
|
||||
|
||||
|
||||
|
||||
|
||||
#[napi(js_name = "Cursor")]
|
||||
#[napi(object, js_name = "Cursor")]
|
||||
pub struct JsCursor {
|
||||
/// range of text change, as char indexes in buffer previous state
|
||||
pub start_row: i32,
|
||||
|
@ -46,7 +42,6 @@ impl From<CodempCursor> for JsCursor {
|
|||
|
||||
#[napi]
|
||||
impl CodempCursorController {
|
||||
|
||||
#[napi(ts_args_type = "fun: (event: JsCursorEvent) => void")]
|
||||
pub fn callback(&self, fun: napi::JsFunction) -> napi::Result<()>{
|
||||
let tsfn : ThreadsafeFunction<JsCursor, ErrorStrategy::Fatal> =
|
||||
|
@ -70,46 +65,14 @@ impl CodempCursorController {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn send(&self, pos: &CodempCursorController) -> napi::Result<()> {
|
||||
Ok(self.send(pos)?)
|
||||
}
|
||||
#[napi(js_name = "send")]
|
||||
pub fn js_send(&self, pos: JsCursor) -> napi::Result<()> {
|
||||
Ok(self.send(crate::api::Cursor::from(pos))?)
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
#[napi(object)]
|
||||
pub struct JsCursorEvent {
|
||||
pub user: String,
|
||||
pub buffer: String,
|
||||
pub start: JsRowCol,
|
||||
pub end: JsRowCol,
|
||||
}
|
||||
|
||||
impl From::<codemp_proto::cursor::CursorEvent> for JsCursorEvent {
|
||||
fn from(value: codemp_proto::cursor::CursorEvent) -> Self {
|
||||
let pos = value.position;
|
||||
let start = pos.start;
|
||||
let end = pos.end;
|
||||
JsCursorEvent {
|
||||
user: Uuid::from(value.user).to_string(),
|
||||
buffer: pos.buffer.into(),
|
||||
start: JsRowCol { row: start.row, col: start.col },
|
||||
end: JsRowCol { row: end.row, col: end.col },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[napi(object)]
|
||||
pub struct JsRowCol {
|
||||
pub row: i32,
|
||||
pub col: i32
|
||||
}
|
||||
|
||||
impl From::<codemp_proto::cursor::RowCol> for JsRowCol {
|
||||
fn from(value: codemp_proto::cursor::RowCol) -> Self {
|
||||
JsRowCol { row: value.row, col: value.col }
|
||||
#[napi(js_name= "try_recv")]
|
||||
pub fn js_try_recv(&self) -> napi::Result<Option<JsCursor>> {
|
||||
Ok(self.try_recv()?.map(|x| JsCursor::from(x)))
|
||||
}
|
||||
}
|
|
@ -6,12 +6,13 @@ pub mod cursor;
|
|||
pub mod buffer;
|
||||
pub mod op_cache;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct JsCodempError(crate::Error);
|
||||
|
||||
impl From::<JsCodempError> for napi::Error {
|
||||
fn from(value: JsCodempError) -> Self {
|
||||
napi::Error::new(napi::Status::GenericFailure, &format!("CodempError: {:?}", value))
|
||||
impl From<crate::Error> for napi::Error {
|
||||
fn from(value: crate::Error) -> Self {
|
||||
let msg = format!("{value}");
|
||||
match value {
|
||||
crate::Error::Deadlocked => napi::Error::new(napi::Status::WouldDeadlock, msg),
|
||||
_ => napi::Error::new(napi::Status::GenericFailure, msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,11 +37,12 @@ impl JsLogger {
|
|||
.with_line_number(false)
|
||||
.with_source_location(false)
|
||||
.compact();
|
||||
tracing_subscriber::fmt()
|
||||
let _initialized = tracing_subscriber::fmt()
|
||||
.event_format(format)
|
||||
.with_max_level(level)
|
||||
.with_writer(std::sync::Mutex::new(JsLoggerProducer(tx)))
|
||||
.init();
|
||||
.try_init()
|
||||
.is_ok();
|
||||
JsLogger(std::sync::Arc::new(tokio::sync::Mutex::new(rx)))
|
||||
}
|
||||
|
||||
|
|
|
@ -36,9 +36,9 @@ impl CodempWorkspace {
|
|||
Ok(self.attach(&path).await?)
|
||||
}
|
||||
|
||||
/*#[napi]
|
||||
pub async fn delete(&self, path: String) -> napi::Result<>{
|
||||
self.0.delete(&path)
|
||||
}*/
|
||||
#[napi(js_name = "delete")]
|
||||
pub async fn js_delete(&self, path: String) -> napi::Result<()> {
|
||||
Ok(self.delete(&path).await?)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue