Skip to content

Commit ca84e29

Browse files
authored
feat: split to create a library (#62)
Not the cleanest split; happy to revise. And also happy for this to not be published until it goes through a few more revisions to clean it up to produce a sensible API. (e.g. MainError probably doesnt belong in the lib)
1 parent 2b7628c commit ca84e29

File tree

3 files changed

+151
-128
lines changed

3 files changed

+151
-128
lines changed

src/lib.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//! pnpm wrapper library.
2+
3+
use indexmap::IndexMap;
4+
use serde::{Deserialize, Serialize};
5+
6+
pub mod error;
7+
pub mod passed_through;
8+
pub mod shell_quoted;
9+
pub mod utils;
10+
pub mod workspace;
11+
12+
/// Structure of `package.json`.
13+
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
14+
#[serde(rename_all = "kebab-case")]
15+
pub struct NodeManifest {
16+
#[serde(default)]
17+
pub name: String,
18+
19+
#[serde(default)]
20+
pub version: String,
21+
22+
#[serde(default)]
23+
pub scripts: IndexMap<String, String>,
24+
}

src/main.rs

Lines changed: 8 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,24 @@
11
use clap::Parser;
22
use cli::Cli;
33
use error::{MainError, PnError};
4-
use indexmap::IndexMap;
54
use pipe_trait::Pipe;
6-
use serde::{Deserialize, Serialize};
75
use shell_quoted::ShellQuoted;
86
use std::{
97
env,
10-
ffi::OsString,
11-
fs::File,
12-
io::{self, ErrorKind, Write},
13-
num::NonZeroI32,
8+
io::{self, Write},
149
path::Path,
15-
process::{exit, Command, Stdio},
10+
process::exit,
1611
};
1712
use yansi::Color::{Black, Red};
1813

1914
mod cli;
20-
mod error;
21-
mod passed_through;
22-
mod shell_quoted;
23-
mod workspace;
2415

25-
/// Structure of `package.json`.
26-
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
27-
#[serde(rename_all = "kebab-case")]
28-
struct NodeManifest {
29-
#[serde(default)]
30-
name: String,
31-
32-
#[serde(default)]
33-
version: String,
34-
35-
#[serde(default)]
36-
scripts: IndexMap<String, String>,
37-
}
16+
use pn::error;
17+
use pn::passed_through;
18+
use pn::shell_quoted;
19+
use pn::utils::*;
20+
use pn::workspace;
21+
use pn::NodeManifest;
3822

3923
fn main() {
4024
match run() {
@@ -113,34 +97,6 @@ fn run() -> Result<(), MainError> {
11397
}
11498
}
11599

116-
fn run_script(name: &str, command: ShellQuoted, cwd: &Path) -> Result<(), MainError> {
117-
let path_env = create_path_env()?;
118-
let status = Command::new("sh")
119-
.current_dir(cwd)
120-
.env("PATH", path_env)
121-
.arg("-c")
122-
.arg(&command)
123-
.stdin(Stdio::inherit())
124-
.stdout(Stdio::inherit())
125-
.stderr(Stdio::inherit())
126-
.spawn()
127-
.map_err(PnError::SpawnProcessError)?
128-
.wait()
129-
.map_err(PnError::WaitProcessError)?
130-
.code()
131-
.map(NonZeroI32::new);
132-
match status {
133-
Some(None) => return Ok(()),
134-
Some(Some(status)) => PnError::ScriptError {
135-
name: name.to_string(),
136-
status,
137-
},
138-
None => PnError::UnexpectedTermination { command },
139-
}
140-
.pipe(MainError::Pn)
141-
.pipe(Err)
142-
}
143-
144100
fn list_scripts(
145101
mut stdout: impl Write,
146102
script_map: impl IntoIterator<Item = (String, String)>,
@@ -153,82 +109,6 @@ fn list_scripts(
153109
Ok(())
154110
}
155111

156-
fn pass_to_pnpm(args: &[String]) -> Result<(), MainError> {
157-
let status = Command::new("pnpm")
158-
.args(args)
159-
.stdin(Stdio::inherit())
160-
.stdout(Stdio::inherit())
161-
.stderr(Stdio::inherit())
162-
.spawn()
163-
.map_err(PnError::SpawnProcessError)?
164-
.wait()
165-
.map_err(PnError::WaitProcessError)?
166-
.code()
167-
.map(NonZeroI32::new);
168-
Err(match status {
169-
Some(None) => return Ok(()),
170-
Some(Some(status)) => MainError::Sub(status),
171-
None => MainError::Pn(PnError::UnexpectedTermination {
172-
command: ShellQuoted::from_command_and_args("pnpm".into(), args),
173-
}),
174-
})
175-
}
176-
177-
fn pass_to_sub(command: ShellQuoted) -> Result<(), MainError> {
178-
let path_env = create_path_env()?;
179-
let status = Command::new("sh")
180-
.env("PATH", path_env)
181-
.arg("-c")
182-
.arg(&command)
183-
.stdin(Stdio::inherit())
184-
.stdout(Stdio::inherit())
185-
.stderr(Stdio::inherit())
186-
.spawn()
187-
.map_err(PnError::SpawnProcessError)?
188-
.wait()
189-
.map_err(PnError::WaitProcessError)?
190-
.code()
191-
.map(NonZeroI32::new);
192-
Err(match status {
193-
Some(None) => return Ok(()),
194-
Some(Some(status)) => MainError::Sub(status),
195-
None => MainError::Pn(PnError::UnexpectedTermination { command }),
196-
})
197-
}
198-
199-
fn read_package_manifest(manifest_path: &Path) -> Result<NodeManifest, MainError> {
200-
manifest_path
201-
.pipe(File::open)
202-
.map_err(|error| match error.kind() {
203-
ErrorKind::NotFound => PnError::NoPkgManifest {
204-
file: manifest_path.to_path_buf(),
205-
},
206-
_ => PnError::FsError {
207-
path: manifest_path.to_path_buf(),
208-
error,
209-
},
210-
})?
211-
.pipe(serde_json::de::from_reader::<_, NodeManifest>)
212-
.map_err(|err| {
213-
MainError::Pn(PnError::ParseJsonError {
214-
file: manifest_path.to_path_buf(),
215-
message: err.to_string(),
216-
})
217-
})
218-
}
219-
220-
fn create_path_env() -> Result<OsString, MainError> {
221-
let existing_paths = env::var_os("PATH");
222-
let existing_paths = existing_paths.iter().flat_map(env::split_paths);
223-
Path::new("node_modules")
224-
.join(".bin")
225-
.pipe(std::iter::once)
226-
.chain(existing_paths)
227-
.pipe(env::join_paths)
228-
.map_err(PnError::NodeBinPathError)
229-
.map_err(MainError::from)
230-
}
231-
232112
#[cfg(test)]
233113
mod tests {
234114
use super::*;

src/utils.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use crate::{
2+
error::{MainError, PnError},
3+
shell_quoted::ShellQuoted,
4+
NodeManifest,
5+
};
6+
use pipe_trait::Pipe;
7+
use std::{
8+
env,
9+
ffi::OsString,
10+
fs::File,
11+
io::ErrorKind,
12+
num::NonZeroI32,
13+
path::Path,
14+
process::{Command, Stdio},
15+
};
16+
17+
pub fn run_script(name: &str, command: ShellQuoted, cwd: &Path) -> Result<(), MainError> {
18+
let path_env = create_path_env()?;
19+
let status = Command::new("sh")
20+
.current_dir(cwd)
21+
.env("PATH", path_env)
22+
.arg("-c")
23+
.arg(&command)
24+
.stdin(Stdio::inherit())
25+
.stdout(Stdio::inherit())
26+
.stderr(Stdio::inherit())
27+
.spawn()
28+
.map_err(PnError::SpawnProcessError)?
29+
.wait()
30+
.map_err(PnError::WaitProcessError)?
31+
.code()
32+
.map(NonZeroI32::new);
33+
match status {
34+
Some(None) => return Ok(()),
35+
Some(Some(status)) => PnError::ScriptError {
36+
name: name.to_string(),
37+
status,
38+
},
39+
None => PnError::UnexpectedTermination { command },
40+
}
41+
.pipe(MainError::Pn)
42+
.pipe(Err)
43+
}
44+
45+
pub fn pass_to_pnpm(args: &[String]) -> Result<(), MainError> {
46+
let status = Command::new("pnpm")
47+
.args(args)
48+
.stdin(Stdio::inherit())
49+
.stdout(Stdio::inherit())
50+
.stderr(Stdio::inherit())
51+
.spawn()
52+
.map_err(PnError::SpawnProcessError)?
53+
.wait()
54+
.map_err(PnError::WaitProcessError)?
55+
.code()
56+
.map(NonZeroI32::new);
57+
Err(match status {
58+
Some(None) => return Ok(()),
59+
Some(Some(status)) => MainError::Sub(status),
60+
None => MainError::Pn(PnError::UnexpectedTermination {
61+
command: ShellQuoted::from_command_and_args("pnpm".into(), args),
62+
}),
63+
})
64+
}
65+
66+
pub fn pass_to_sub(command: ShellQuoted) -> Result<(), MainError> {
67+
let path_env = create_path_env()?;
68+
let status = Command::new("sh")
69+
.env("PATH", path_env)
70+
.arg("-c")
71+
.arg(&command)
72+
.stdin(Stdio::inherit())
73+
.stdout(Stdio::inherit())
74+
.stderr(Stdio::inherit())
75+
.spawn()
76+
.map_err(PnError::SpawnProcessError)?
77+
.wait()
78+
.map_err(PnError::WaitProcessError)?
79+
.code()
80+
.map(NonZeroI32::new);
81+
Err(match status {
82+
Some(None) => return Ok(()),
83+
Some(Some(status)) => MainError::Sub(status),
84+
None => MainError::Pn(PnError::UnexpectedTermination { command }),
85+
})
86+
}
87+
88+
pub fn read_package_manifest(manifest_path: &Path) -> Result<NodeManifest, MainError> {
89+
manifest_path
90+
.pipe(File::open)
91+
.map_err(|error| match error.kind() {
92+
ErrorKind::NotFound => PnError::NoPkgManifest {
93+
file: manifest_path.to_path_buf(),
94+
},
95+
_ => PnError::FsError {
96+
path: manifest_path.to_path_buf(),
97+
error,
98+
},
99+
})?
100+
.pipe(serde_json::de::from_reader::<_, NodeManifest>)
101+
.map_err(|err| {
102+
MainError::Pn(PnError::ParseJsonError {
103+
file: manifest_path.to_path_buf(),
104+
message: err.to_string(),
105+
})
106+
})
107+
}
108+
109+
pub fn create_path_env() -> Result<OsString, MainError> {
110+
let existing_paths = env::var_os("PATH");
111+
let existing_paths = existing_paths.iter().flat_map(env::split_paths);
112+
Path::new("node_modules")
113+
.join(".bin")
114+
.pipe(std::iter::once)
115+
.chain(existing_paths)
116+
.pipe(env::join_paths)
117+
.map_err(PnError::NodeBinPathError)
118+
.map_err(MainError::from)
119+
}

0 commit comments

Comments
 (0)