Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 5 additions & 13 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --verbose
- run: cargo test --verbose --features=client

test-doc:
runs-on: ubuntu-latest
Expand All @@ -28,7 +28,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo doc --features=serialize
- run: cargo doc --features=client,serialize

test-beta:
runs-on: ubuntu-latest
Expand All @@ -47,7 +47,7 @@ jobs:
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
- run: cargo test --verbose
- run: cargo test --verbose --features=client

test-build:
needs: [test-unit]
Expand Down Expand Up @@ -75,21 +75,13 @@ jobs:
test-coverage:
needs: [test-unit]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
features:
- java
- js
- py
- lua
steps:
- uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --no-default-features --features=ci,${{ matrix.features }},test-coverage,py-abi3,lua-jit tests::coverage
- run: cargo test --no-default-features --features=ci,test-coverage,py-abi3,lua-jit tests::coverage

test-functional:
needs: [test-build]
Expand All @@ -100,7 +92,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --verbose --features=test-e2e tests::e2e
- run: cargo test --verbose --features=ci,test-e2e tests::e2e
env:
CODEMP_TEST_USERNAME_ALICE: ${{ secrets.CODEMP_TEST_USERNAME_ALICE }}
CODEMP_TEST_PASSWORD_ALICE: ${{ secrets.CODEMP_TEST_PASSWORD_ALICE }}
Expand Down
29 changes: 16 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,14 @@ thiserror = "2.0"
# crdt
diamond-types = "1.0"
# proto
codemp-proto = { git = "https://github.com/hexedtech/codemp-proto", rev = "6b45fd7bd7c03ef60234880c59157481def4ca71", features = ["client"] }
uuid = { version = "1.17", features = ["v4"] }
tonic = { version = "0.14", features = ["tls-native-roots"] }
codemp-proto = { git = "https://github.com/hexedtech/codemp-proto", rev = "6b45fd7bd7c03ef60234880c59157481def4ca71", optional = true }
# api
tokio = { version = "1.47", features = ["macros", "rt-multi-thread", "sync"] }
xxhash-rust = { version = "0.8", features = ["xxh3"] }
# client
tokio-stream = "0.1"
dashmap = "6.1"
tokio = { version = "1.47", features = ["macros", "rt-multi-thread", "sync"], optional = true }
tonic = { version = "0.14", features = ["tls-native-roots"], optional = true }
tokio-stream = { version = "0.1", optional = true }
dashmap = { version = "6.1", optional = true }

# glue (multiple)
tracing-subscriber = { version = "0.3", optional = true }
Expand All @@ -66,6 +65,7 @@ async-trait = { version = "0.1", optional = true }
serde = { version = "1.0", features = ["derive"], optional = true }
syn = { version = "2.0", features = ["full"], optional = true }
regex = { version = "1.12", optional = true }
uuid = { version = "1.17", features = ["v4"], optional = true }


[build-dependencies]
Expand All @@ -77,17 +77,20 @@ pyo3-introspection = { version = "0.28", optional = true }

[features]
default = ["lua-jit", "py-abi3", "py-extmod"]
proto = ["dep:codemp-proto"]
client = ["proto", "dep:tonic", "dep:tokio", "dep:tokio-stream", "dep:dashmap", "codemp-proto?/client"]
server = ["proto", "codemp-proto?/server"]
# extra
async-trait = ["dep:async-trait"]
serialize = ["dep:serde", "uuid/serde"]
serialize = ["dep:serde", "uuid?/serde"]
# special tests which require more setup
test-e2e = []
test-e2e = ["client", "dep:uuid"]
test-coverage = ["dep:syn", "dep:regex"]
# ffi
java = ["dep:jni", "dep:tracing-subscriber", "dep:jni-toolbox", "codemp-proto/java"]
js = ["dep:napi-build", "dep:tracing-subscriber", "dep:napi", "dep:napi-derive", "codemp-proto/js"]
py = ["dep:pyo3", "dep:tracing-subscriber", "dep:pyo3-build-config", "dep:pyo3-introspection", "codemp-proto/py"]
lua = ["serialize", "dep:mlua", "dep:mlua-serde-derive", "dep:tracing-subscriber", "codemp-proto/lua"]
java = ["client", "dep:jni", "dep:tracing-subscriber", "dep:jni-toolbox", "codemp-proto/java"]
js = ["client", "dep:napi-build", "dep:tracing-subscriber", "dep:napi", "dep:napi-derive", "codemp-proto/js"]
py = ["client", "dep:pyo3", "dep:tracing-subscriber", "dep:pyo3-build-config", "dep:pyo3-introspection", "codemp-proto/py"]
lua = ["client", "serialize", "dep:mlua", "dep:mlua-serde-derive", "dep:tracing-subscriber", "dep:uuid", "codemp-proto/lua"]
# ffi variants
lua-jit = ["mlua?/luajit"]
lua-54 = ["mlua?/lua54"]
Expand All @@ -98,7 +101,7 @@ ci = []


[package.metadata.docs.rs] # enabled features when building on docs.rs
features = ["serialize"]
features = ["client", "serialize"]

[profile.release]
opt-level = 'z'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@
* This is the only object you are expected to hold yourself; unlike all the others,
* there are no copies of it managed exclusively by the library. When this is garbage
* collected, it will free the underlying memory.
* A Client is used to join and manage workspaces, and to obtain information about
* A Session is used to join and manage workspaces, and to obtain information about
* the current session.
*/
@Getter
public final class Client {
public final class Session {
private final long ptr;

Client(long ptr) {
Session(long ptr) {
this.ptr = ptr;
Extensions.CLEANER.register(this, () -> free(ptr));
}

/**
* Connects to a remote CodeMP server and creates a {@link Client} instance
* Connects to a remote CodeMP server and creates a {@link Session} instance
* for interacting with it.
* @param config a {@link Config} object containing the connection settings
* @return a holder for the Client's pointer
* @return a holder for the Session's pointer
* @throws ConnectionException if an error occurs in communicating with the server
*/
public static native Client connect(Config config) throws ConnectionException;
public static native Session connect(Config config) throws ConnectionException;

private static native UserInfo current_user(long self);

Expand Down Expand Up @@ -222,7 +222,7 @@ public SessionEvent recv() throws ControllerException {
return recv(this.ptr);
}

private static native void callback(long self, Consumer<Client> cb);
private static native void callback(long self, Consumer<Session> cb);

/**
* Registers a callback to be invoked whenever a {@link SessionEvent} occurs.
Expand All @@ -231,7 +231,7 @@ public SessionEvent recv() throws ControllerException {
* you should probably spawn a new thread in here, to avoid deadlocking
* @see Extensions#drive(boolean)
*/
public void callback(Consumer<Client> cb) {
public void callback(Consumer<Session> cb) {
callback(this.ptr, cb);
}

Expand Down
62 changes: 31 additions & 31 deletions dist/lua/annotations.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ function StringArrayPromise:cancel() end
function StringArrayPromise:and_then(cb) end


---@class (exact) ClientPromise : Promise
local ClientPromise = {}
---@class (exact) SessionPromise : Promise
local SessionPromise = {}
--- block until promise is ready and return value
--- @return Client
function ClientPromise:await() end
--- @return Session
function SessionPromise:await() end
--- cancel promise execution
function ClientPromise:cancel() end
---@param cb fun(x: Client) callback to invoke
function SessionPromise:cancel() end
---@param cb fun(x: Session) callback to invoke
---invoke callback asynchronously as soon as promise is ready
function ClientPromise:and_then(cb) end
function SessionPromise:and_then(cb) end


---@class (exact) WorkspacePromise : Promise
Expand Down Expand Up @@ -216,107 +216,107 @@ function WorkspaceIdentifierListPromise:and_then(cb) end
-- [[ END ASYNC STUFF ]]


---@class (exact) Client
---@class (exact) Session
---the effective local client, handling connecting to codemp server
local Client = {}
local Session = {}

---@return UserInfo
---current logged in user for this client
function Client:current_user() end
function Session:current_user() end

---@return string[]
---array of all currently active workspace names
function Client:active_workspaces() end
function Session:active_workspaces() end

---@return NilPromise
---@async
---@nodiscard
---refresh current user token if possible
function Client:refresh() end
function Session:refresh() end

---@param user string workspace owning user
---@param ws string workspace id to connect to
---@return WorkspacePromise
---@async
---@nodiscard
---join requested workspace if possible and subscribe to event bus
function Client:attach_workspace(user, ws) end
function Session:attach_workspace(user, ws) end

---@param ws string workspace id to create
---@return NilPromise
---@async
---@nodiscard
---create a new workspace with given id
function Client:create_workspace(ws) end
function Session:create_workspace(ws) end

---@param user string workspace owning user
---@param ws string workspace id to leave
---leave workspace with given id, detaching and disconnecting
function Client:leave_workspace(user, ws) end
function Session:leave_workspace(user, ws) end

---@param ws string workspace id to delete
---@return NilPromise
---@async
---@nodiscard
---delete workspace with given id
function Client:delete_workspace(ws) end
function Session:delete_workspace(ws) end

---@param user string user owning the workspace to quit
---@param workspace string workspace to quit
---@return NilPromise
---@async
---@nodiscard
---quit a joined workspace, by user + workspace name
function Client:quit_workspace(user, workspace) end
function Session:quit_workspace(user, workspace) end

---@param user string user inviting us
---@param workspace string workspace being invited to
---@return NilPromise
---@async
---@nodiscard
---accept an invite to a new workspace
function Client:accept_invite(user, workspace) end
function Session:accept_invite(user, workspace) end

---@param user string user inviting us
---@param workspace string workspace being invited to
---@return NilPromise
---@async
---@nodiscard
---reject an invite to a new workspace
function Client:reject_invite(user, workspace) end
function Session:reject_invite(user, workspace) end

---@param ws string workspace id to delete
---@param user string user name to invite to given workspace
---@return NilPromise
---@async
---@nodiscard
---grant user acccess to workspace
function Client:invite_to_workspace(ws, user) end
function Session:invite_to_workspace(ws, user) end

---@return WorkspaceIdentifierListPromise
---@async
---@nodiscard
---fetch and list owned workspaces
function Client:fetch_owned_workspaces() end
function Session:fetch_owned_workspaces() end

---@return WorkspaceIdentifierListPromise
---@async
---@nodiscard
---fetch and list joined workspaces
function Client:fetch_joined_workspaces() end
function Session:fetch_joined_workspaces() end

---@param user string user owning this workspace
---@param ws string workspace id to get
---@return Workspace?
---get an active workspace by name
function Client:get_workspace(user, ws) end
function Session:get_workspace(user, ws) end

---@param user string username to lookup
---@return UserInfoPromise
---@async
---@nodiscard
---get full user info for given username from server
function Client:get_user_info(user) end
function Session:get_user_info(user) end

---@class (exact) SessionEvent
---@field kind integer (SessionEventKind) event kind
Expand All @@ -327,26 +327,26 @@ function Client:get_user_info(user) end
---@async
---@nodiscard
---try to receive session events, returning nil if none is available
function Client:try_recv() end
function Session:try_recv() end

---@return SessionEventPromise
---@async
---@nodiscard
---block until next client event and return it
function Client:recv() end
function Session:recv() end

---@return NilPromise
---@async
---@nodiscard
---block until next session event without returning it
function Client:poll() end
function Session:poll() end

---clears any previously registered session callback
function Client:clear_callback() end
function Session:clear_callback() end

---@param cb fun(w: Client) callback to invoke on each workspace event received
---@param cb fun(w: Session) callback to invoke on each workspace event received
---register a new callback to be called on session events (replaces any previously registered one)
function Client:callback(cb) end
function Session:callback(cb) end



Expand Down Expand Up @@ -657,7 +657,7 @@ function CursorController:callback(cb) end
local Codemp = {}

---@param config Config configuration for
---@return ClientPromise
---@return SessionPromise
---@async
---@nodiscard
---connect to codemp server, authenticate and return client
Expand Down
12 changes: 8 additions & 4 deletions src/api/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,26 @@ impl Config {
}
}

/// get server host address
#[inline]
pub(crate) fn host(&self) -> &str {
pub fn host(&self) -> &str {
self.host.as_deref().unwrap_or("api.code.mp")
}

/// get server port number
#[inline]
pub(crate) fn port(&self) -> u16 {
pub fn port(&self) -> u16 {
self.port.unwrap_or(50053)
}

/// get whether TLS should be used
#[inline]
pub(crate) fn tls(&self) -> bool {
pub fn tls(&self) -> bool {
self.tls.unwrap_or(true)
}

pub(crate) fn endpoint(&self) -> String {
/// get the actual server uri, combining its parts (tls,host,port)
pub fn endpoint(&self) -> String {
format!(
"{}://{}:{}",
if self.tls() { "https" } else { "http" },
Expand Down
Loading
Loading