Skip to content

Commit 55c2648

Browse files
implement minimal suite of server methods
1 parent 9300694 commit 55c2648

File tree

13 files changed

+382
-119
lines changed

13 files changed

+382
-119
lines changed

src/cli.rs

+6
Original file line numberDiff line numberDiff line change
@@ -257,4 +257,10 @@ pub enum Commands {
257257

258258
/// Update the tcli ecosystem schema.
259259
UpdateSchema,
260+
261+
/// Start the tcli server.
262+
Server {
263+
#[clap(long, default_value = "./")]
264+
project_path: PathBuf,
265+
},
260266
}

src/error.rs

+34-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::path::{Path, PathBuf};
22

3+
use crate::server::ServerError;
34
use crate::ts::error::ApiError;
45

56
use crate::game::error::GameError;
@@ -22,21 +23,18 @@ pub enum Error {
2223
Api(#[from] ApiError),
2324

2425
#[error("{0}")]
25-
Io(#[from] IoError),
26-
27-
#[error("{0}")]
28-
JsonParse(#[from] serde_json::Error),
26+
Server(#[from] ServerError),
2927

3028
#[error("{0}")]
31-
TomlDeserialize(#[from] toml::de::Error),
29+
Io(#[from] IoError),
3230

3331
#[error("{0}")]
34-
TomlSerialize(#[from] toml::ser::Error),
32+
Parse(#[from] ParseError),
3533
}
3634

3735
#[derive(Debug, thiserror::Error)]
3836
pub enum IoError {
39-
#[error("A file IO error occured: {0}.")]
37+
#[error("A file IO error occurred: {0}.")]
4038
Native(std::io::Error, Option<PathBuf>),
4139

4240
#[error("File not found: {0}.")]
@@ -64,6 +62,18 @@ pub enum IoError {
6462
ZipError(#[from] zip::result::ZipError),
6563
}
6664

65+
#[derive(Debug, thiserror::Error)]
66+
pub enum ParseError {
67+
#[error("A json parse error occurred: {0}")]
68+
Json(#[from] serde_json::Error),
69+
70+
#[error("A toml serialization error occurred: {0}")]
71+
TomlSe(#[from] toml::ser::Error),
72+
73+
#[error("A toml deserialization error occured: {0}")]
74+
TomlDe(#[from] toml::de::Error),
75+
}
76+
6777
impl From<std::io::Error> for Error {
6878
fn from(value: std::io::Error) -> Self {
6979
Self::Io(IoError::Native(value, None))
@@ -82,6 +92,23 @@ impl From<zip::result::ZipError> for Error {
8292
}
8393
}
8494

95+
impl From<serde_json::Error> for Error {
96+
fn from(value: serde_json::Error) -> Self {
97+
Self::Parse(ParseError::Json(value))
98+
}
99+
}
100+
impl From<toml::de::Error> for Error {
101+
fn from(value: toml::de::Error) -> Self {
102+
Self::Parse(ParseError::TomlDe(value))
103+
}
104+
}
105+
106+
impl From<toml::ser::Error> for Error {
107+
fn from(value: toml::ser::Error) -> Self {
108+
Self::Parse(ParseError::TomlSe(value))
109+
}
110+
}
111+
85112
pub trait IoResultToTcli<R> {
86113
fn map_fs_error(self, path: impl AsRef<Path>) -> Result<R, IoError>;
87114
}

src/main.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![allow(dead_code)]
22

3+
use std::io::{self, Stdin};
34
use std::path::PathBuf;
45

56
use clap::Parser;
@@ -31,7 +32,7 @@ mod error;
3132
mod game;
3233
mod package;
3334
mod project;
34-
// mod server;
35+
mod server;
3536
mod ts;
3637
mod ui;
3738
mod util;
@@ -338,6 +339,8 @@ async fn main() -> Result<(), Error> {
338339
let graph = DependencyGraph::from_graph(lock.package_graph);
339340

340341
for package in graph.digest() {
342+
println!("{}", package);
343+
341344
let package = Package::from_any(package).await?;
342345
let Some(meta) = package.get_metadata().await? else {
343346
continue;
@@ -350,6 +353,13 @@ async fn main() -> Result<(), Error> {
350353
Ok(())
351354
}
352355
},
356+
Commands::Server { project_path }=> {
357+
let read = io::stdin();
358+
let write = io::stdout();
359+
server::spawn(read, write, &project_path).await?;
360+
361+
Ok(())
362+
},
353363
};
354364

355365
test

src/package/cache.rs

+4
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ pub async fn get_temp_zip_file(
2121
pub fn get_cache_location(package: &PackageReference) -> PathBuf {
2222
CACHE_LOCATION.join(package.to_string())
2323
}
24+
25+
pub fn is_cached(package: &PackageReference) -> bool {
26+
CACHE_LOCATION.join(package.to_string()).exists()
27+
}

src/package/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
mod cache;
1+
pub mod cache;
22
pub mod index;
33
pub mod install;
44
pub mod resolver;

src/project/lock.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use md5::Md5;
88
use serde::{Deserialize, Deserializer, Serialize, Serializer};
99

1010
use crate::error::Error;
11-
use crate::package::Package;
11+
use crate::package::{Package, PackageMetadata};
1212
use crate::package::resolver::{DependencyGraph, InnerDepGraph};
1313

1414
#[derive(Serialize, Deserialize, Debug)]
@@ -76,6 +76,20 @@ impl LockFile {
7676

7777
Ok(())
7878
}
79+
80+
pub async fn installed_packages(self) -> Result<Vec<PackageMetadata>, Error> {
81+
let graph = DependencyGraph::from_graph(self.package_graph);
82+
let mut packages = Vec::new();
83+
84+
for package in graph.digest() {
85+
let package = Package::from_any(package).await?;
86+
if let Some(meta) = package.get_metadata().await? {
87+
packages.push(meta);
88+
}
89+
}
90+
91+
Ok(packages)
92+
}
7993
}
8094

8195
pub fn serialize<S: Serializer>(

src/server/lock.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
33

44
/// Only one server process can "own" a project at a single time.
55
/// We enforce this exclusive access through the creation and deletion of this lockfile.
6-
const LOCKFILE: &'static str = ".server-lock";
6+
const LOCKFILE: &str = ".server-lock";
77

88
pub struct ProjectLock {
99
file: File,
@@ -27,7 +27,7 @@ impl ProjectLock {
2727
impl Drop for ProjectLock {
2828
fn drop(&mut self) {
2929
// The file handle is dropped before this, so we can safely delete it.
30-
fs::remove_file(&self.path).unwrap();
30+
fs::remove_file(&self.path).expect("Failed to remove lockfile.");
3131
}
3232
}
3333

src/server/method/mod.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
pub mod package;
22
pub mod project;
33

4+
use std::sync::RwLock;
5+
6+
use futures::channel::mpsc::Sender;
47
use serde::de::DeserializeOwned;
58
use serde::{Deserialize, Serialize};
69

10+
use crate::project::Project;
11+
712
use self::package::PackageMethod;
813
use self::project::ProjectMethod;
9-
use super::Error;
14+
use super::proto::Response;
15+
use super::{Error, ServerError};
16+
17+
pub trait Routeable {
18+
async fn route(&self, ctx: RwLock<Project>, send: Sender<Result<Response, Error>>);
19+
}
1020

1121
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
1222
pub enum Method {
@@ -22,18 +32,18 @@ impl Method {
2232
let (namespace, name) = (
2333
split
2434
.next()
25-
.ok_or_else(|| Error::InvalidMethod(method.into()))?,
35+
.ok_or_else(|| ServerError::InvalidMethod(method.into()))?,
2636
split
2737
.next()
28-
.ok_or_else(|| Error::InvalidMethod(method.into()))?,
38+
.ok_or_else(|| ServerError::InvalidMethod(method.into()))?,
2939
);
3040

3141
// Route namespaces to the appropriate enum variants for construction.
3242
Ok(match namespace {
3343
"exit" => Self::Exit,
3444
"project" => Self::Project(ProjectMethod::from_value(name, value)?),
3545
"package" => Self::Package(PackageMethod::from_value(name, value)?),
36-
x => Err(Error::InvalidMethod(x.into()))?,
46+
x => Err(ServerError::InvalidMethod(x.into()))?,
3747
})
3848
}
3949
}

src/server/method/package.rs

+45-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,61 @@
11
use serde::{Deserialize, Serialize};
22

3+
use crate::package::{cache, Package};
4+
use crate::server::proto::{Id, Response};
5+
use crate::ts::package_reference::PackageReference;
6+
use crate::TCLI_HOME;
7+
use crate::server::{Runtime, ServerError};
8+
use crate::package::index::PackageIndex;
9+
310
use super::Error;
411

512
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
613
pub enum PackageMethod {
714
/// Get metadata about this package.
8-
GetMetadata,
15+
GetMetadata(GetMetadata),
916
/// Determine if the package exists within the cache.
10-
IsCached,
17+
IsCached(IsCached),
18+
/// Syncronize the package index.
19+
SyncIndex,
1120
}
1221

1322
impl PackageMethod {
1423
pub fn from_value(method: &str, value: serde_json::Value) -> Result<Self, Error> {
1524
Ok(match method {
16-
"get_metadata" => Self::GetMetadata,
17-
"is_cached" => Self::IsCached,
18-
x => Err(Error::InvalidMethod(x.into()))?,
25+
"get_metadata" => Self::GetMetadata(super::parse_value(value)?),
26+
"is_cached" => Self::IsCached(super::parse_value(value)?),
27+
"sync_index" => Self::SyncIndex,
28+
x => Err(ServerError::InvalidMethod(x.into()))?,
1929
})
2030
}
31+
32+
pub async fn route(&self, rt: &mut Runtime) -> Result<(), Error> {
33+
match self {
34+
Self::GetMetadata(data) => {
35+
let index = PackageIndex::open(&TCLI_HOME).await?;
36+
let package = index.get_package(&data.package).unwrap();
37+
rt.send(Response::data_ok(Id::String("diowadaw".into()), package));
38+
},
39+
Self::IsCached(data) => {
40+
let is_cached = cache::is_cached(&data.package);
41+
rt.send(Response::data_ok(Id::String("dwdawdwa".into()), is_cached));
42+
}
43+
Self::SyncIndex => {
44+
PackageIndex::sync(&TCLI_HOME).await?;
45+
rt.send(Response::ok(Id::String("dwada".into())));
46+
},
47+
}
48+
49+
Ok(())
50+
}
51+
}
52+
53+
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
54+
pub struct IsCached {
55+
package: PackageReference,
56+
}
57+
58+
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
59+
pub struct GetMetadata {
60+
package: PackageReference,
2161
}

0 commit comments

Comments
 (0)