1 use std::time::Instant;
2 
3 use crate::{cli, hex::ApiKeyCommand, http::HttpClient};
4 use gleam_core::{
5     build::Package,
6     config::{DocsPage, PackageConfig},
7     error::Error,
8     hex,
9     io::HttpClient as _,
10     paths, Result,
11 };
12 
13 static TOKEN_NAME: &str = concat!(env!("CARGO_PKG_NAME"), " (", env!("CARGO_PKG_VERSION"), ")");
14 
remove(package: String, version: String) -> Result<(), Error>15 pub fn remove(package: String, version: String) -> Result<(), Error> {
16     let config = hexpm::Config::new();
17     let http = HttpClient::new();
18 
19     // Start event loop so we can run async functions to call the Hex API
20     let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
21 
22     // Get login creds from user
23     let username = cli::ask("https://hex.pm username")?;
24     let password = cli::ask_password("https://hex.pm password")?;
25 
26     // Authenticate with API
27     let request = hexpm::create_api_key_request(&username, &password, TOKEN_NAME, &config);
28     let response = runtime.block_on(http.send(request))?;
29     let token = hexpm::create_api_key_response(response).map_err(Error::hex)?;
30 
31     // Remove docs from API
32     let request =
33         hexpm::remove_docs_request(&package, &version, &token, &config).map_err(Error::hex)?;
34     let response = runtime.block_on(http.send(request))?;
35     hexpm::remove_docs_response(response).map_err(Error::hex)?;
36 
37     // Done!
38     println!(
39         "The docs for {} {} have been removed from HexDocs",
40         package, version
41     );
42     Ok(())
43 }
44 
build() -> Result<()>45 pub fn build() -> Result<()> {
46     let config = crate::config::root_config()?;
47     let out = paths::build_docs(&config.name);
48     let mut compiled = crate::build::main()?;
49     let outputs = build_documentation(&config, &mut compiled)?;
50 
51     // Write
52     crate::fs::delete_dir(&out)?;
53     crate::fs::write_outputs_under(&outputs, &out)?;
54 
55     println!(
56         "\nThe documentation for {package} has been rendered to \n./{out}/index.html",
57         package = config.name,
58         out = out.to_string_lossy()
59     );
60 
61     // We're done!
62     Ok(())
63 }
64 
build_documentation( config: &PackageConfig, compiled: &mut Package, ) -> Result<Vec<gleam_core::io::OutputFile>, Error>65 pub(crate) fn build_documentation(
66     config: &PackageConfig,
67     compiled: &mut Package,
68 ) -> Result<Vec<gleam_core::io::OutputFile>, Error> {
69     compiled.attach_doc_and_module_comments();
70     cli::print_generating_documentation();
71     let mut pages = vec![DocsPage {
72         title: "README".to_string(),
73         path: "index.html".to_string(),
74         source: paths::readme(), // TODO: support non markdown READMEs. Or a default if there is none.
75     }];
76     pages.extend(config.documentation.pages.iter().cloned());
77     let outputs = gleam_core::docs::generate_html(config, compiled.modules.as_slice(), &pages);
78     Ok(outputs)
79 }
80 
81 pub struct PublishCommand {
82     config: PackageConfig,
83     archive: Vec<u8>,
84 }
85 
86 impl PublishCommand {
new() -> Result<Self>87     pub fn new() -> Result<Self> {
88         let config = crate::config::root_config()?;
89         let mut compiled = crate::build::main()?;
90         let outputs = build_documentation(&config, &mut compiled)?;
91         let archive = crate::fs::create_tar_archive(outputs)?;
92         Ok(Self { config, archive })
93     }
94 
publish() -> Result<()>95     pub fn publish() -> Result<()> {
96         Self::new()?.run()
97     }
98 }
99 
100 impl ApiKeyCommand for PublishCommand {
with_api_key( &mut self, handle: &tokio::runtime::Handle, hex_config: &hexpm::Config, api_key: &str, ) -> Result<()>101     fn with_api_key(
102         &mut self,
103         handle: &tokio::runtime::Handle,
104         hex_config: &hexpm::Config,
105         api_key: &str,
106     ) -> Result<()> {
107         let start = Instant::now();
108         cli::print_publishing_documentation();
109         handle.block_on(hex::publish_documentation(
110             &self.config.name,
111             &self.config.version,
112             std::mem::take(&mut self.archive),
113             api_key,
114             hex_config,
115             &HttpClient::new(),
116         ))?;
117         cli::print_published(start.elapsed());
118         Ok(())
119     }
120 }
121