mirror of
https://github.com/hexedtech/codemp.git
synced 2024-11-22 07:14:50 +01:00
feat: add specific feature flag to specify building python without abi.
This is needed because if we want to ship to sublime, having the `pyo3/abi-*` feature enabled will result in a wheel that needs the `python3.dll` (f****g windows) which sublime does not ship. This works fine for Linux and Mac Os, but for windows we will need to build without abi and for Python3.8 directly for sublime specifically and also with the abi for the generic python wheel to be used everywhere else.
This commit is contained in:
parent
9218e9e9c7
commit
f6c0b878cb
12 changed files with 143 additions and 80 deletions
|
@ -50,7 +50,7 @@ napi = { version = "2.16", features = ["full"], optional = true }
|
||||||
napi-derive = { version="2.16", optional = true}
|
napi-derive = { version="2.16", optional = true}
|
||||||
|
|
||||||
# glue (python)
|
# glue (python)
|
||||||
pyo3 = { version = "0.22", features = ["extension-module", "abi3-py38"], optional = true}
|
pyo3 = { version = "0.22", features = ["extension-module"], optional = true}
|
||||||
|
|
||||||
# extra
|
# extra
|
||||||
async-trait = { version = "0.1", optional = true }
|
async-trait = { version = "0.1", optional = true }
|
||||||
|
@ -71,7 +71,8 @@ serialize = ["dep:serde", "uuid/serde"]
|
||||||
rust = [] # used for ci matrix
|
rust = [] # used for ci matrix
|
||||||
java = ["lazy_static", "jni", "tracing-subscriber"]
|
java = ["lazy_static", "jni", "tracing-subscriber"]
|
||||||
js = ["napi-build", "tracing-subscriber", "napi", "napi-derive"]
|
js = ["napi-build", "tracing-subscriber", "napi", "napi-derive"]
|
||||||
py = ["pyo3", "tracing-subscriber", "pyo3-build-config"]
|
py-noabi = ["pyo3", "tracing-subscriber", "pyo3-build-config"]
|
||||||
|
py = ["py-noabi", "pyo3/abi3-py38"]
|
||||||
lua = ["mlua-codemp-patch", "tracing-subscriber", "lazy_static", "serialize"]
|
lua = ["mlua-codemp-patch", "tracing-subscriber", "lazy_static", "serialize"]
|
||||||
lua54 =["lua", "mlua-codemp-patch/lua54"]
|
lua54 =["lua", "mlua-codemp-patch/lua54"]
|
||||||
luajit = ["lua", "mlua-codemp-patch/luajit"]
|
luajit = ["lua", "mlua-codemp-patch/luajit"]
|
||||||
|
|
4
build.rs
4
build.rs
|
@ -1,7 +1,7 @@
|
||||||
#[cfg(feature = "js")]
|
#[cfg(feature = "js")]
|
||||||
extern crate napi_build;
|
extern crate napi_build;
|
||||||
|
|
||||||
#[cfg(feature = "py")]
|
#[cfg(any(feature = "py", feature = "py-noabi"))]
|
||||||
extern crate pyo3_build_config;
|
extern crate pyo3_build_config;
|
||||||
|
|
||||||
/// The main method of the buildscript, required by some glue modules.
|
/// The main method of the buildscript, required by some glue modules.
|
||||||
|
@ -11,7 +11,7 @@ fn main() {
|
||||||
napi_build::setup();
|
napi_build::setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "py")]
|
#[cfg(any(feature = "py", feature = "py-noabi"))]
|
||||||
{
|
{
|
||||||
pyo3_build_config::add_extension_module_link_args();
|
pyo3_build_config::add_extension_module_link_args();
|
||||||
}
|
}
|
||||||
|
|
4
dist/py/pyproject.toml
vendored
4
dist/py/pyproject.toml
vendored
|
@ -2,7 +2,7 @@
|
||||||
name = "codemp"
|
name = "codemp"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
description = "code multiplexer"
|
description = "code multiplexer"
|
||||||
requires-python = ">= 3.8"
|
requires-python = ">=3.8"
|
||||||
license = "GPL-3.0-only"
|
license = "GPL-3.0-only"
|
||||||
keywords = ["codemp", "cooperative", "rust", "python"]
|
keywords = ["codemp", "cooperative", "rust", "python"]
|
||||||
authors = [
|
authors = [
|
||||||
|
@ -28,7 +28,7 @@ requires = ["maturin>=1.0,<2.0"]
|
||||||
build-backend = "maturin"
|
build-backend = "maturin"
|
||||||
|
|
||||||
[tool.maturin]
|
[tool.maturin]
|
||||||
features = ["py", "pyo3/extension-module"]
|
features = ["py"]
|
||||||
manifest-path = "../../Cargo.toml"
|
manifest-path = "../../Cargo.toml"
|
||||||
python-source = "src"
|
python-source = "src"
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
///
|
///
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
#[cfg_attr(feature = "js", napi_derive::napi(object))]
|
#[cfg_attr(feature = "js", napi_derive::napi(object))]
|
||||||
#[cfg_attr(feature = "py", pyo3::pyclass(get_all))]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyo3::pyclass(get_all))]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct TextChange {
|
pub struct TextChange {
|
||||||
/// Range start of text change, as char indexes in buffer previous state.
|
/// Range start of text change, as char indexes in buffer previous state.
|
||||||
|
@ -43,7 +43,7 @@ impl TextChange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "py", pyo3::pymethods)]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyo3::pymethods)]
|
||||||
impl TextChange {
|
impl TextChange {
|
||||||
/// Returns true if this [`TextChange`] deletes existing text.
|
/// Returns true if this [`TextChange`] deletes existing text.
|
||||||
///
|
///
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
/// http{tls?'s':''}://{host}:{port}
|
/// http{tls?'s':''}://{host}:{port}
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[cfg_attr(feature = "js", napi_derive::napi(object))]
|
#[cfg_attr(feature = "js", napi_derive::napi(object))]
|
||||||
#[cfg_attr(feature = "py", pyo3::pyclass(get_all, set_all))]
|
#[cfg_attr(
|
||||||
|
any(feature = "py", feature = "py-noabi"),
|
||||||
|
pyo3::pyclass(get_all, set_all)
|
||||||
|
)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// user identifier used to register, possibly your email
|
/// user identifier used to register, possibly your email
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
//! ### Cursor
|
//! ### Cursor
|
||||||
//! Represents the position of a remote user's cursor.
|
//! Represents the position of a remote user's cursor.
|
||||||
|
|
||||||
#[cfg(feature = "py")]
|
#[cfg(any(feature = "py", feature = "py-noabi"))]
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
/// User cursor position in a buffer
|
/// User cursor position in a buffer
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
#[cfg_attr(feature = "py", pyclass)]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyclass)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
// #[cfg_attr(feature = "py", pyo3(crate = "reexported::pyo3"))]
|
// #[cfg_attr(feature = "py", pyo3(crate = "reexported::pyo3"))]
|
||||||
pub struct Cursor {
|
pub struct Cursor {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use codemp_proto::workspace::workspace_event::Event as WorkspaceEventInner;
|
||||||
|
|
||||||
/// Event in a [crate::Workspace].
|
/// Event in a [crate::Workspace].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(feature = "py", pyo3::pyclass)]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyo3::pyclass)]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
/// Fired when the file tree changes.
|
/// Fired when the file tree changes.
|
||||||
|
|
|
@ -18,7 +18,7 @@ use super::worker::DeltaRequest;
|
||||||
/// Each buffer controller internally tracks the last acknowledged state, remaining always in sync
|
/// Each buffer controller internally tracks the last acknowledged state, remaining always in sync
|
||||||
/// with the server while allowing to procedurally receive changes while still sending new ones.
|
/// with the server while allowing to procedurally receive changes while still sending new ones.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(feature = "py", pyo3::pyclass)]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyo3::pyclass)]
|
||||||
#[cfg_attr(feature = "js", napi_derive::napi)]
|
#[cfg_attr(feature = "js", napi_derive::napi)]
|
||||||
pub struct BufferController(pub(crate) Arc<BufferControllerInner>);
|
pub struct BufferController(pub(crate) Arc<BufferControllerInner>);
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,25 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use tonic::{service::interceptor::InterceptedService, transport::{Channel, Endpoint}};
|
use tonic::{
|
||||||
|
service::interceptor::InterceptedService,
|
||||||
use crate::{api::User, errors::{ConnectionResult, RemoteResult}, ext::InternallyMutable, network, workspace::Workspace};
|
transport::{Channel, Endpoint},
|
||||||
use codemp_proto::{
|
|
||||||
auth::{auth_client::AuthClient, LoginRequest},
|
|
||||||
common::{Empty, Token}, session::{session_client::SessionClient, InviteRequest, WorkspaceRequest},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "py")]
|
use crate::{
|
||||||
|
api::User,
|
||||||
|
errors::{ConnectionResult, RemoteResult},
|
||||||
|
ext::InternallyMutable,
|
||||||
|
network,
|
||||||
|
workspace::Workspace,
|
||||||
|
};
|
||||||
|
use codemp_proto::{
|
||||||
|
auth::{auth_client::AuthClient, LoginRequest},
|
||||||
|
common::{Empty, Token},
|
||||||
|
session::{session_client::SessionClient, InviteRequest, WorkspaceRequest},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(any(feature = "py", feature = "py-noabi"))]
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
/// A `codemp` client handle.
|
/// A `codemp` client handle.
|
||||||
|
@ -22,7 +32,7 @@ use pyo3::prelude::*;
|
||||||
/// A new [`Client`] can be obtained with [`Client::connect`].
|
/// A new [`Client`] can be obtained with [`Client::connect`].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(feature = "js", napi_derive::napi)]
|
#[cfg_attr(feature = "js", napi_derive::napi)]
|
||||||
#[cfg_attr(feature = "py", pyclass)]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyclass)]
|
||||||
pub struct Client(Arc<ClientInner>);
|
pub struct Client(Arc<ClientInner>);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -42,7 +52,8 @@ impl Client {
|
||||||
let channel = Endpoint::from_shared(config.endpoint())?.connect().await?;
|
let channel = Endpoint::from_shared(config.endpoint())?.connect().await?;
|
||||||
let mut auth = AuthClient::new(channel.clone());
|
let mut auth = AuthClient::new(channel.clone());
|
||||||
|
|
||||||
let resp = auth.login(LoginRequest {
|
let resp = auth
|
||||||
|
.login(LoginRequest {
|
||||||
username: config.username.clone(),
|
username: config.username.clone(),
|
||||||
password: config.password.clone(),
|
password: config.password.clone(),
|
||||||
})
|
})
|
||||||
|
@ -52,20 +63,26 @@ impl Client {
|
||||||
let claims = InternallyMutable::new(resp.token);
|
let claims = InternallyMutable::new(resp.token);
|
||||||
|
|
||||||
// TODO move this one into network.rs
|
// TODO move this one into network.rs
|
||||||
let session = SessionClient::with_interceptor(
|
let session =
|
||||||
channel, network::SessionInterceptor(claims.channel())
|
SessionClient::with_interceptor(channel, network::SessionInterceptor(claims.channel()));
|
||||||
);
|
|
||||||
|
|
||||||
Ok(Client(Arc::new(ClientInner {
|
Ok(Client(Arc::new(ClientInner {
|
||||||
user: resp.user.into(),
|
user: resp.user.into(),
|
||||||
workspaces: DashMap::default(),
|
workspaces: DashMap::default(),
|
||||||
claims, auth, session, config
|
claims,
|
||||||
|
auth,
|
||||||
|
session,
|
||||||
|
config,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Refresh session token.
|
/// Refresh session token.
|
||||||
pub async fn refresh(&self) -> RemoteResult<()> {
|
pub async fn refresh(&self) -> RemoteResult<()> {
|
||||||
let new_token = self.0.auth.clone().refresh(self.0.claims.get())
|
let new_token = self
|
||||||
|
.0
|
||||||
|
.auth
|
||||||
|
.clone()
|
||||||
|
.refresh(self.0.claims.get())
|
||||||
.await?
|
.await?
|
||||||
.into_inner();
|
.into_inner();
|
||||||
self.0.claims.set(new_token);
|
self.0.claims.set(new_token);
|
||||||
|
@ -74,25 +91,36 @@ impl Client {
|
||||||
|
|
||||||
/// Attempt to create a new workspace with given name.
|
/// Attempt to create a new workspace with given name.
|
||||||
pub async fn create_workspace(&self, name: impl AsRef<str>) -> RemoteResult<()> {
|
pub async fn create_workspace(&self, name: impl AsRef<str>) -> RemoteResult<()> {
|
||||||
self.0.session
|
self.0
|
||||||
|
.session
|
||||||
.clone()
|
.clone()
|
||||||
.create_workspace(WorkspaceRequest { workspace: name.as_ref().to_string() })
|
.create_workspace(WorkspaceRequest {
|
||||||
|
workspace: name.as_ref().to_string(),
|
||||||
|
})
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete an existing workspace if possible.
|
/// Delete an existing workspace if possible.
|
||||||
pub async fn delete_workspace(&self, name: impl AsRef<str>) -> RemoteResult<()> {
|
pub async fn delete_workspace(&self, name: impl AsRef<str>) -> RemoteResult<()> {
|
||||||
self.0.session
|
self.0
|
||||||
|
.session
|
||||||
.clone()
|
.clone()
|
||||||
.delete_workspace(WorkspaceRequest { workspace: name.as_ref().to_string() })
|
.delete_workspace(WorkspaceRequest {
|
||||||
|
workspace: name.as_ref().to_string(),
|
||||||
|
})
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invite user with given username to the given workspace, if possible.
|
/// Invite user with given username to the given workspace, if possible.
|
||||||
pub async fn invite_to_workspace(&self, workspace_name: impl AsRef<str>, user_name: impl AsRef<str>) -> RemoteResult<()> {
|
pub async fn invite_to_workspace(
|
||||||
self.0.session
|
&self,
|
||||||
|
workspace_name: impl AsRef<str>,
|
||||||
|
user_name: impl AsRef<str>,
|
||||||
|
) -> RemoteResult<()> {
|
||||||
|
self.0
|
||||||
|
.session
|
||||||
.clone()
|
.clone()
|
||||||
.invite_to_workspace(InviteRequest {
|
.invite_to_workspace(InviteRequest {
|
||||||
workspace: workspace_name.as_ref().to_string(),
|
workspace: workspace_name.as_ref().to_string(),
|
||||||
|
@ -104,7 +132,9 @@ impl Client {
|
||||||
|
|
||||||
/// List all available workspaces, also filtering between those owned and those invited to.
|
/// List all available workspaces, also filtering between those owned and those invited to.
|
||||||
pub async fn list_workspaces(&self, owned: bool, invited: bool) -> RemoteResult<Vec<String>> {
|
pub async fn list_workspaces(&self, owned: bool, invited: bool) -> RemoteResult<Vec<String>> {
|
||||||
let mut workspaces = self.0.session
|
let mut workspaces = self
|
||||||
|
.0
|
||||||
|
.session
|
||||||
.clone()
|
.clone()
|
||||||
.list_workspaces(Empty {})
|
.list_workspaces(Empty {})
|
||||||
.await?
|
.await?
|
||||||
|
@ -112,17 +142,25 @@ impl Client {
|
||||||
|
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
|
|
||||||
if owned { out.append(&mut workspaces.owned) }
|
if owned {
|
||||||
if invited { out.append(&mut workspaces.invited) }
|
out.append(&mut workspaces.owned)
|
||||||
|
}
|
||||||
|
if invited {
|
||||||
|
out.append(&mut workspaces.invited)
|
||||||
|
}
|
||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Join and return a [`Workspace`].
|
/// Join and return a [`Workspace`].
|
||||||
pub async fn join_workspace(&self, workspace: impl AsRef<str>) -> ConnectionResult<Workspace> {
|
pub async fn join_workspace(&self, workspace: impl AsRef<str>) -> ConnectionResult<Workspace> {
|
||||||
let token = self.0.session
|
let token = self
|
||||||
|
.0
|
||||||
|
.session
|
||||||
.clone()
|
.clone()
|
||||||
.access_workspace(WorkspaceRequest { workspace: workspace.as_ref().to_string() })
|
.access_workspace(WorkspaceRequest {
|
||||||
|
workspace: workspace.as_ref().to_string(),
|
||||||
|
})
|
||||||
.await?
|
.await?
|
||||||
.into_inner();
|
.into_inner();
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,20 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use tokio::sync::{mpsc, oneshot, watch};
|
use tokio::sync::{mpsc, oneshot, watch};
|
||||||
|
|
||||||
use crate::{api::{controller::ControllerCallback, Controller, Cursor}, errors::ControllerResult};
|
use crate::{
|
||||||
use codemp_proto::{cursor::{CursorPosition, RowCol}, files::BufferNode};
|
api::{controller::ControllerCallback, Controller, Cursor},
|
||||||
|
errors::ControllerResult,
|
||||||
|
};
|
||||||
|
use codemp_proto::{
|
||||||
|
cursor::{CursorPosition, RowCol},
|
||||||
|
files::BufferNode,
|
||||||
|
};
|
||||||
|
|
||||||
/// A [Controller] for asynchronously sending and receiving [Cursor] event.
|
/// A [Controller] for asynchronously sending and receiving [Cursor] event.
|
||||||
///
|
///
|
||||||
/// An unique [CursorController] exists for each active [crate::Workspace].
|
/// An unique [CursorController] exists for each active [crate::Workspace].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(feature = "py", pyo3::pyclass)]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyo3::pyclass)]
|
||||||
#[cfg_attr(feature = "js", napi_derive::napi)]
|
#[cfg_attr(feature = "js", napi_derive::napi)]
|
||||||
pub struct CursorController(pub(crate) Arc<CursorControllerInner>);
|
pub struct CursorController(pub(crate) Arc<CursorControllerInner>);
|
||||||
|
|
||||||
|
@ -31,11 +37,23 @@ impl Controller<Cursor> for CursorController {
|
||||||
if cursor.start > cursor.end {
|
if cursor.start > cursor.end {
|
||||||
std::mem::swap(&mut cursor.start, &mut cursor.end);
|
std::mem::swap(&mut cursor.start, &mut cursor.end);
|
||||||
}
|
}
|
||||||
Ok(self.0.op.send(CursorPosition {
|
Ok(self
|
||||||
buffer: BufferNode { path: cursor.buffer },
|
.0
|
||||||
start: RowCol { row: cursor.start.0, col: cursor.start.1 },
|
.op
|
||||||
end: RowCol { row: cursor.end.0, col: cursor.end.1 },
|
.send(CursorPosition {
|
||||||
}).await?)
|
buffer: BufferNode {
|
||||||
|
path: cursor.buffer,
|
||||||
|
},
|
||||||
|
start: RowCol {
|
||||||
|
row: cursor.start.0,
|
||||||
|
col: cursor.start.1,
|
||||||
|
},
|
||||||
|
end: RowCol {
|
||||||
|
row: cursor.end.0,
|
||||||
|
col: cursor.end.1,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_recv(&self) -> ControllerResult<Option<Cursor>> {
|
async fn try_recv(&self) -> ControllerResult<Option<Cursor>> {
|
||||||
|
|
|
@ -56,5 +56,5 @@ pub mod lua;
|
||||||
pub mod js;
|
pub mod js;
|
||||||
|
|
||||||
/// python bindings, built with [pyo3]
|
/// python bindings, built with [pyo3]
|
||||||
#[cfg(feature = "py")]
|
#[cfg(any(feature = "py", feature = "py-noabi"))]
|
||||||
pub mod python;
|
pub mod python;
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
||||||
cursor::{self, worker::CursorWorker},
|
cursor::{self, worker::CursorWorker},
|
||||||
errors::{ConnectionResult, ControllerResult, RemoteResult},
|
errors::{ConnectionResult, ControllerResult, RemoteResult},
|
||||||
ext::InternallyMutable,
|
ext::InternallyMutable,
|
||||||
network::Services
|
network::Services,
|
||||||
};
|
};
|
||||||
|
|
||||||
use codemp_proto::{
|
use codemp_proto::{
|
||||||
|
@ -33,7 +33,7 @@ use uuid::Uuid;
|
||||||
use napi_derive::napi;
|
use napi_derive::napi;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(feature = "py", pyo3::pyclass)]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyo3::pyclass)]
|
||||||
#[cfg_attr(feature = "js", napi)]
|
#[cfg_attr(feature = "js", napi)]
|
||||||
pub struct Workspace(Arc<WorkspaceInner>);
|
pub struct Workspace(Arc<WorkspaceInner>);
|
||||||
|
|
||||||
|
@ -59,7 +59,8 @@ impl Workspace {
|
||||||
claims: tokio::sync::watch::Receiver<codemp_proto::common::Token>, // TODO ughh receiving this
|
claims: tokio::sync::watch::Receiver<codemp_proto::common::Token>, // TODO ughh receiving this
|
||||||
) -> ConnectionResult<Self> {
|
) -> ConnectionResult<Self> {
|
||||||
let workspace_claim = InternallyMutable::new(token);
|
let workspace_claim = InternallyMutable::new(token);
|
||||||
let services = Services::try_new(&config.endpoint(), claims, workspace_claim.channel()).await?;
|
let services =
|
||||||
|
Services::try_new(&config.endpoint(), claims, workspace_claim.channel()).await?;
|
||||||
let ws_stream = services.ws().attach(Empty {}).await?.into_inner();
|
let ws_stream = services.ws().attach(Empty {}).await?.into_inner();
|
||||||
|
|
||||||
let (tx, rx) = mpsc::channel(128);
|
let (tx, rx) = mpsc::channel(128);
|
||||||
|
@ -126,11 +127,11 @@ impl Workspace {
|
||||||
|
|
||||||
let (tx, rx) = mpsc::channel(256);
|
let (tx, rx) = mpsc::channel(256);
|
||||||
let mut req = tonic::Request::new(tokio_stream::wrappers::ReceiverStream::new(rx));
|
let mut req = tonic::Request::new(tokio_stream::wrappers::ReceiverStream::new(rx));
|
||||||
req.metadata_mut()
|
req.metadata_mut().insert(
|
||||||
.insert(
|
|
||||||
"buffer",
|
"buffer",
|
||||||
tonic::metadata::MetadataValue::try_from(credentials.token)
|
tonic::metadata::MetadataValue::try_from(credentials.token).map_err(|e| {
|
||||||
.map_err(|e| tonic::Status::internal(format!("failed representing token to string: {e}")))?,
|
tonic::Status::internal(format!("failed representing token to string: {e}"))
|
||||||
|
})?,
|
||||||
);
|
);
|
||||||
let stream = self.0.services.buf().attach(req).await?.into_inner();
|
let stream = self.0.services.buf().attach(req).await?.into_inner();
|
||||||
|
|
||||||
|
@ -282,14 +283,18 @@ impl Workspace {
|
||||||
/// A filter may be applied, and it may be strict (equality check) or not (starts_with check).
|
/// A filter may be applied, and it may be strict (equality check) or not (starts_with check).
|
||||||
// #[cfg_attr(feature = "js", napi)] // https://github.com/napi-rs/napi-rs/issues/1120
|
// #[cfg_attr(feature = "js", napi)] // https://github.com/napi-rs/napi-rs/issues/1120
|
||||||
pub fn filetree(&self, filter: Option<&str>, strict: bool) -> Vec<String> {
|
pub fn filetree(&self, filter: Option<&str>, strict: bool) -> Vec<String> {
|
||||||
self.0.filetree.iter()
|
self.0
|
||||||
.filter(|f| filter.map_or(true, |flt| {
|
.filetree
|
||||||
|
.iter()
|
||||||
|
.filter(|f| {
|
||||||
|
filter.map_or(true, |flt| {
|
||||||
if strict {
|
if strict {
|
||||||
f.as_str() == flt
|
f.as_str() == flt
|
||||||
} else {
|
} else {
|
||||||
f.starts_with(flt)
|
f.starts_with(flt)
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
|
})
|
||||||
.map(|f| f.clone())
|
.map(|f| f.clone())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -315,9 +320,7 @@ impl Workspace {
|
||||||
match ev {
|
match ev {
|
||||||
// user
|
// user
|
||||||
WorkspaceEventInner::Join(UserJoin { user }) => {
|
WorkspaceEventInner::Join(UserJoin { user }) => {
|
||||||
inner
|
inner.users.insert(user.id.uuid(), user.into());
|
||||||
.users
|
|
||||||
.insert(user.id.uuid(), user.into());
|
|
||||||
}
|
}
|
||||||
WorkspaceEventInner::Leave(UserLeave { user }) => {
|
WorkspaceEventInner::Leave(UserLeave { user }) => {
|
||||||
inner.users.remove(&user.id.uuid());
|
inner.users.remove(&user.id.uuid());
|
||||||
|
@ -364,8 +367,8 @@ impl Drop for WorkspaceInner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "py", pyo3::pyclass(eq, eq_int))]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyo3::pyclass(eq, eq_int))]
|
||||||
#[cfg_attr(feature = "py", derive(PartialEq))]
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), derive(PartialEq))]
|
||||||
pub enum DetachResult {
|
pub enum DetachResult {
|
||||||
NotAttached,
|
NotAttached,
|
||||||
Detaching,
|
Detaching,
|
||||||
|
|
Loading…
Reference in a new issue