perseus_cli/
lib.rs

1#![doc = include_str!("../README.proj.md")]
2/*!
3## Packages
4
5This is the API documentation for the `perseus-cli` package, which acts as a frontend for abstracting away a lot of Perseus' internal complexity. Note that Perseus mostly uses
6[the book](https://framesurge.sh/perseus/en-US) for documentation, and this should mostly be used as a secondary reference source. You can also find full usage examples
7[here](https://github.com/framesurge/perseus/tree/main/examples).
8
9## Why is this here?
10
11Usually, binary packages wouldn't have API documentation like this, but the Perseus CLI uses a hybrid structure of a library and a binary, which allows it to be used as a library in applications
12that build on Perseus. Note that this area of using Perseus is currently almost entirely undocumented, and there may be major hiccups! If you'd like to help us out, please [open a PR](https://github.com/framesurge/perseus/pulls/new) for
13the documentation you'd like to see on this front!
14*/
15
16#![deny(missing_docs)]
17
18mod build;
19mod check;
20mod cmd;
21mod deploy;
22pub mod errors;
23mod export;
24mod export_error_page;
25mod init;
26mod install;
27/// Parsing utilities for arguments.
28pub mod parse;
29mod prepare;
30mod reload_server;
31mod serve;
32mod serve_exported;
33mod snoop;
34mod test;
35mod thread;
36mod tinker;
37
38use errors::*;
39use std::path::PathBuf;
40use std::{fs, path::Path};
41
42/// The current version of the CLI, extracted from the crate version.
43pub const PERSEUS_VERSION: &str = env!("CARGO_PKG_VERSION");
44pub use build::build;
45pub use check::check;
46pub use deploy::deploy;
47pub use export::export;
48pub use export_error_page::export_error_page;
49pub use init::{init, new};
50pub use install::{get_tools_dir, Tools};
51pub use prepare::check_env;
52pub use reload_server::{order_reload, run_reload_server};
53pub use serve::serve;
54pub use serve_exported::serve_exported;
55pub use snoop::{snoop_build, snoop_server, snoop_wasm_build};
56pub use test::test;
57pub use tinker::tinker;
58
59/// Creates the `dist/` directory in the project root, which is necessary
60/// for Cargo to be able to put its build artifacts in there.
61pub fn create_dist(dir: &Path) -> Result<(), ExecutionError> {
62    let target = dir.join("dist");
63    if !target.exists() {
64        fs::create_dir(target).map_err(|err| ExecutionError::CreateDistFailed { source: err })?;
65    }
66    Ok(())
67}
68
69/// Deletes the entire `dist/` directory. Notably, this is where we keep
70/// several Cargo artifacts, so this means the next build will be much
71/// slower.
72pub fn delete_dist(dir: PathBuf) -> Result<(), ExecutionError> {
73    let target = dir.join("dist");
74    if target.exists() {
75        if let Err(err) = fs::remove_dir_all(&target) {
76            return Err(ExecutionError::RemoveArtifactsFailed {
77                target: target.to_str().map(|s| s.to_string()),
78                source: err,
79            });
80        }
81    }
82
83    Ok(())
84}
85
86/// Deletes build artifacts in `dist/static` or `dist/pkg` and replaces the
87/// directory.
88pub fn delete_artifacts(dir: PathBuf, dir_to_remove: &str) -> Result<(), ExecutionError> {
89    let mut target = dir;
90    target.extend(["dist", dir_to_remove]);
91    // We'll only delete the directory if it exists, otherwise we're fine
92    if target.exists() {
93        if let Err(err) = fs::remove_dir_all(&target) {
94            return Err(ExecutionError::RemoveArtifactsFailed {
95                target: target.to_str().map(|s| s.to_string()),
96                source: err,
97            });
98        }
99    }
100    // No matter what, it's gone now, so recreate it
101    // We also create parent directories because that's an issue for some reason in
102    // Docker (see #69)
103    if let Err(err) = fs::create_dir_all(&target) {
104        return Err(ExecutionError::RemoveArtifactsFailed {
105            target: target.to_str().map(|s| s.to_string()),
106            source: err,
107        });
108    }
109
110    Ok(())
111}
112
113/// Gets the name of the user's crate from their `Cargo.toml` (assumed to be in
114/// the root of the given directory).
115pub fn get_user_crate_name(dir: &Path) -> Result<String, ExecutionError> {
116    let manifest = cargo_toml::Manifest::from_path(dir.join("Cargo.toml"))
117        .map_err(|err| ExecutionError::GetManifestFailed { source: err })?;
118    let name = manifest
119        .package
120        .ok_or(ExecutionError::CrateNameNotPresentInManifest)?
121        .name;
122    Ok(name)
123}
124
125/// The paths of files/folders that are excluded from the watcher system by
126/// default. These can be overriden using the custom watcher system.
127///
128/// *Note: following v0.4.0-beta.18, these will only affect the top-level paths
129/// with these names, rather than any paths with these names. Further exclusions
130/// should be manually specified.*
131pub static WATCH_EXCLUSIONS: &[&str] =
132    &["dist", "target", "target_engine", "target_browser", ".git"];