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