Skip to content

Commit 3b55040

Browse files
committed
WIP refactor to AtomicUrl
1 parent adf4990 commit 3b55040

File tree

21 files changed

+325
-97
lines changed

21 files changed

+325
-97
lines changed

.cargo/config.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[build]
2+
rustc-wrapper = '/Users/joep/.cargo/bin/sccache'
3+
[target.x86_64-unknown-linux-gnu]
4+
rustflags = [
5+
'-Clink-arg=-fuse-ld=lld',
6+
'-Zshare-generics=y',
7+
]
8+
linker = '/usr/bin/clang'
9+
10+
[target.x86_64-pc-windows-msvc]
11+
rustflags = ['-Zshare-generics=y']
12+
linker = 'rust-lld.exe'
13+
14+
[target.x86_64-apple-darwin]
15+
rustflags = [
16+
'-C',
17+
'link-arg=-fuse-ld=/usr/local/bin/zld',
18+
'-Zshare-generics=y',
19+
'-Csplit-debuginfo=unpacked',
20+
]
21+
[profile.dev]
22+
opt-level = 0
23+
debug = 2
24+
incremental = true
25+
codegen-units = 512
26+
27+
[profile.release]
28+
opt-level = 3
29+
debug = 0
30+
incremental = false
31+
codegen-units = 256
32+
split-debuginfo = '...'

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ fn set_agent_config() -> CLIResult<Config> {
5555
"No config found at {:?}. Let's create one!",
5656
&agent_config_path
5757
);
58-
let server = promptly::prompt("What's the base url of your Atomic Server?")?;
58+
let server: String = promptly::prompt("What's the base url of your Atomic Server?")?;
5959
let agent = promptly::prompt("What's the URL of your Agent?")?;
6060
let private_key = promptly::prompt("What's the private key of this Agent?")?;
6161
let config = atomic_lib::config::Config {
@@ -282,7 +282,7 @@ fn exec_command(context: &mut Context) -> AtomicResult<()> {
282282
fn list(context: &mut Context) {
283283
let mut string = String::new();
284284
for (shortname, url) in context.mapping.lock().unwrap().clone().into_iter() {
285-
string.push_str(&*format!(
285+
string.push_str(&format!(
286286
"{0: <15}{1: <10} \n",
287287
shortname.blue().bold(),
288288
url
@@ -297,7 +297,7 @@ fn tpf(context: &Context) -> AtomicResult<()> {
297297
let subject = tpf_value(subcommand_matches.value_of("subject").unwrap());
298298
let property = tpf_value(subcommand_matches.value_of("property").unwrap());
299299
let value = tpf_value(subcommand_matches.value_of("value").unwrap());
300-
let endpoint = format!("{}/tpf", &context.get_write_context().server);
300+
let endpoint = context.store.get_server_url().path_tpf().to_string();
301301
let resources =
302302
atomic_lib::client::fetch_tpf(&endpoint, subject, property, value, &context.store)?;
303303
for r in resources {

cli/src/new.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ fn prompt_field(
148148
println!("Only letters, numbers and dashes - no spaces or special characters.");
149149
return Ok(None);
150150
}
151-
None => (return Ok(None)),
151+
None => return Ok(None),
152152
}
153153
}
154154
DataType::Integer => {
@@ -158,7 +158,7 @@ fn prompt_field(
158158
Some(nr) => {
159159
input = Some(nr.to_string());
160160
}
161-
None => (return Ok(None)),
161+
None => return Ok(None),
162162
}
163163
}
164164
DataType::Float => {
@@ -168,7 +168,7 @@ fn prompt_field(
168168
Some(nr) => {
169169
input = Some(nr.to_string());
170170
}
171-
None => (return Ok(None)),
171+
None => return Ok(None),
172172
}
173173
}
174174
DataType::Date => {
@@ -184,7 +184,7 @@ fn prompt_field(
184184
println!("Not a valid date.");
185185
return Ok(None);
186186
}
187-
None => (return Ok(None)),
187+
None => return Ok(None),
188188
}
189189
}
190190
DataType::AtomicUrl => loop {
@@ -264,7 +264,7 @@ fn prompt_field(
264264
Some(nr) => {
265265
input = Some(nr.to_string());
266266
}
267-
None => (return Ok(None)),
267+
None => return Ok(None),
268268
}
269269
}
270270
DataType::Unsupported(unsup) => {
@@ -277,7 +277,7 @@ fn prompt_field(
277277
Some(nr) => {
278278
input = Some(nr);
279279
}
280-
None => (return Ok(None)),
280+
None => return Ok(None),
281281
}
282282
}
283283
DataType::Boolean => {
@@ -290,7 +290,7 @@ fn prompt_field(
290290
}
291291
return Ok(Some("false".to_string()));
292292
}
293-
None => (return Ok(None)),
293+
None => return Ok(None),
294294
}
295295
}
296296
};

cli/src/print.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ pub const SERIALIZE_OPTIONS: [&str; 7] =
1616
pub fn get_serialization(argmatches: &ArgMatches) -> AtomicResult<Format> {
1717
let format = if let Some(preferred_format) = argmatches.value_of("as") {
1818
match preferred_format {
19-
"pretty" => (Format::Pretty),
20-
"json" => (Format::Json),
21-
"jsonld" => (Format::JsonLd),
22-
"jsonad" => (Format::JsonAd),
23-
"nt" => (Format::NTriples),
24-
"turtle" => (Format::NTriples),
25-
"n3" => (Format::NTriples),
19+
"pretty" => Format::Pretty,
20+
"json" => Format::Json,
21+
"jsonld" => Format::JsonLd,
22+
"jsonad" => Format::JsonAd,
23+
"nt" => Format::NTriples,
24+
"turtle" => Format::NTriples,
25+
"n3" => Format::NTriples,
2626
format => {
2727
return Err(
2828
format!("As {} not supported. Try {:?}", format, SERIALIZE_OPTIONS).into(),

lib/src/agents.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,29 @@ impl Agent {
4343
pub fn new(name: Option<&str>, store: &impl Storelike) -> AtomicResult<Agent> {
4444
let keypair = generate_keypair()?;
4545

46-
Ok(Agent::new_from_private_key(name, store, &keypair.private))
46+
Agent::new_from_private_key(name, store, &keypair.private)
4747
}
4848

4949
pub fn new_from_private_key(
5050
name: Option<&str>,
5151
store: &impl Storelike,
5252
private_key: &str,
53-
) -> Agent {
53+
) -> AtomicResult<Agent> {
5454
let keypair = generate_public_key(private_key);
55+
println!("server url: {}", store.get_server_url());
56+
let subject = store
57+
.get_server_url()
58+
.url()
59+
.join(&format!("agents/{}", &keypair.public))?
60+
.to_string();
5561

56-
Agent {
62+
Ok(Agent {
5763
private_key: Some(keypair.private),
58-
public_key: keypair.public.clone(),
59-
subject: format!("{}/agents/{}", store.get_server_url(), keypair.public),
64+
public_key: keypair.public,
65+
subject,
6066
name: name.map(|x| x.to_owned()),
6167
created_at: crate::utils::now(),
62-
}
68+
})
6369
}
6470

6571
pub fn new_from_public_key(store: &impl Storelike, public_key: &str) -> AtomicResult<Agent> {

lib/src/atomic_url.rs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use serde::{Deserialize, Serialize, Serializer};
2+
use url::Url;
3+
4+
use crate::{
5+
errors::AtomicResult,
6+
urls::{PATH_COMMITS, PATH_IMPORT, PATH_PATH, PATH_TPF},
7+
utils::random_string,
8+
};
9+
10+
#[derive(Debug, Clone, PartialEq, Eq)]
11+
/// Wrapper for URLs / subjects.
12+
/// Has a bunch of methods for finding or creating commonly used paths.
13+
pub struct AtomicUrl {
14+
url: Url,
15+
}
16+
17+
impl AtomicUrl {
18+
pub fn new(url: Url) -> Self {
19+
Self { url }
20+
}
21+
22+
pub fn as_str(&self) -> &str {
23+
self.url.as_str()
24+
}
25+
26+
/// Returns the URL to the `/tpf` endpoint
27+
pub fn path_tpf(&self) -> Self {
28+
let mut url = self.url.clone();
29+
url.set_path(PATH_TPF);
30+
Self { url }
31+
}
32+
33+
/// Returns the URL to the `/import` endpoint
34+
pub fn path_import(&self) -> Self {
35+
let mut url = self.url.clone();
36+
url.set_path(PATH_IMPORT);
37+
Self { url }
38+
}
39+
/// Returns the URL to the `/commits` endpoint
40+
pub fn path_commits(&self) -> Self {
41+
let mut url = self.url.clone();
42+
url.set_path(PATH_COMMITS);
43+
Self { url }
44+
}
45+
46+
/// Returns the URL to the `/path` endpoint
47+
pub fn path_path(&self) -> Self {
48+
let mut url = self.url.clone();
49+
url.set_path(PATH_PATH);
50+
Self { url }
51+
}
52+
53+
/// Returns a new URL generated from the provided path_shortname and a random string.
54+
/// ```
55+
/// let url = AtomicUrl::new(Url::parse("https://example.com").unwrap());
56+
/// let generated = url.generate("my-type");
57+
/// assert!(generated.to_string().starts_with("https://example.com/my-type/"));
58+
/// ```
59+
pub fn generate_random(&self, path_shortname: &str) -> Self {
60+
let mut url = self.url.clone();
61+
let path = format!("{path_shortname}/{}", random_string(10));
62+
url.set_path(&path);
63+
Self { url }
64+
}
65+
66+
/// Adds a path to a URL
67+
pub fn join(mut self, path: &str) -> AtomicResult<Self> {
68+
self.url = self.url.join(path)?;
69+
Ok(self)
70+
}
71+
72+
pub fn subdomain(&self) -> Option<String> {
73+
let url = self.url.clone();
74+
let host = url.host_str().unwrap();
75+
let parts: Vec<&str> = host.split('.').collect();
76+
if parts.len() > 2 {
77+
Some(parts[0].to_string())
78+
} else {
79+
None
80+
}
81+
}
82+
83+
/// Returns the inner {url::Url} struct that has a bunch of regular URL methods
84+
/// Useful if you need the host or something.
85+
pub fn url(&self) -> Url {
86+
self.url.clone()
87+
}
88+
}
89+
90+
impl TryFrom<&str> for AtomicUrl {
91+
type Error = url::ParseError;
92+
93+
fn try_from(value: &str) -> Result<Self, Self::Error> {
94+
let url = Url::parse(value)?;
95+
Ok(Self { url })
96+
}
97+
}
98+
99+
impl Serialize for AtomicUrl {
100+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
101+
where
102+
S: Serializer,
103+
{
104+
serializer.serialize_str(self.url.as_str())
105+
}
106+
}
107+
108+
impl<'de> Deserialize<'de> for AtomicUrl {
109+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
110+
where
111+
D: serde::Deserializer<'de>,
112+
{
113+
let s = String::deserialize(deserializer)?;
114+
let url = Url::parse(&s).map_err(serde::de::Error::custom)?;
115+
Ok(Self { url })
116+
}
117+
}
118+
119+
impl std::fmt::Display for AtomicUrl {
120+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121+
write!(f, "{}", self.url)
122+
}
123+
}
124+
125+
#[cfg(test)]
126+
mod test {
127+
use super::*;
128+
129+
#[test]
130+
fn test_url() {
131+
let _should_fail = AtomicUrl::try_from("nonsense").unwrap_err();
132+
let _should_succeed = AtomicUrl::try_from("http://localhost/someUrl").unwrap();
133+
}
134+
135+
#[test]
136+
fn join_url() {
137+
let start = "http://localhost/someUrl";
138+
let mut url = AtomicUrl::try_from(start).unwrap();
139+
140+
assert_eq!(url.to_string(), start);
141+
url = url.join("/123").unwrap();
142+
assert_eq!(url.to_string(), "http://localhost/someUrl/123")
143+
}
144+
145+
#[test]
146+
fn subdomain() {
147+
let sub = "http://test.example.com";
148+
assert_eq!(
149+
AtomicUrl::try_from(sub).unwrap().subdomain(),
150+
Some("test".to_string())
151+
);
152+
let no_sub = "http://example.com";
153+
assert_eq!(AtomicUrl::try_from(no_sub).unwrap().subdomain(), None);
154+
}
155+
}

lib/src/commit.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,12 +425,16 @@ impl Commit {
425425
#[tracing::instrument(skip(store))]
426426
pub fn into_resource(self, store: &impl Storelike) -> AtomicResult<Resource> {
427427
let commit_subject = match self.signature.as_ref() {
428-
Some(sig) => format!("{}/commits/{}", store.get_server_url(), sig),
428+
Some(sig) => store.get_server_url().path_commits().join(sig)?.to_string(),
429429
None => {
430430
let now = crate::utils::now();
431431
format!("{}/commitsUnsigned/{}", store.get_server_url(), now)
432432
}
433433
};
434+
println!(
435+
"commit subject: {}",
436+
store.get_server_url().path_commits().join("adwdawawd")?
437+
);
434438
let mut resource = Resource::new_instance(urls::COMMIT, store)?;
435439
resource.set_subject(commit_subject);
436440
resource.set_propval_unsafe(
@@ -752,7 +756,7 @@ mod test {
752756
let private_key = "CapMWIhFUT+w7ANv9oCPqrHrwZpkP2JhzF9JnyT6WcI=";
753757
let store = crate::Store::init().unwrap();
754758
store.populate().unwrap();
755-
let agent = Agent::new_from_private_key(None, &store, private_key);
759+
let agent = Agent::new_from_private_key(None, &store, private_key).unwrap();
756760
assert_eq!(
757761
&agent.subject,
758762
"local:store/agents/7LsjMW5gOfDdJzK/atgjQ1t20J/rw8MjVg6xwqm+h8U="

0 commit comments

Comments
 (0)