diff --git a/CHANGELOG.md b/CHANGELOG.md index 3582643..a60ba99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). #### Unreleased +- build(deps): bump reqwest from 0.12.7 to 0.12.8 [`#34`](https://github.com/i18nhero/cli/pull/34) +- build(deps): bump tempfile from 3.12.0 to 3.13.0 [`#33`](https://github.com/i18nhero/cli/pull/33) +- refactor: change DEFAULT_API_HOST to api.cli.i18nhero.com [`#32`](https://github.com/i18nhero/cli/pull/32) +- feat: login command [`#31`](https://github.com/i18nhero/cli/pull/31) - build(deps): bump clap_complete from 4.5.26 to 4.5.29 [`#30`](https://github.com/i18nhero/cli/pull/30) - build(deps): bump serde from 1.0.209 to 1.0.210 [`#26`](https://github.com/i18nhero/cli/pull/26) - build(deps): bump clap from 4.5.17 to 4.5.18 [`#27`](https://github.com/i18nhero/cli/pull/27) @@ -27,6 +31,5 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - chore: validation workflow [`#2`](https://github.com/i18nhero/cli/pull/2) - build: setup publishing [`#1`](https://github.com/i18nhero/cli/pull/1) - feat(cli): json5 output (#19) [`#15`](https://github.com/i18nhero/cli/issues/15) -- feat(auth): load auth on init [`32c2455`](https://github.com/i18nhero/cli/commit/32c2455e24b2fd6aa1a5d2cd2fa2710391b5defb) - chore: setup workspace [`11b6f6c`](https://github.com/i18nhero/cli/commit/11b6f6c749b6ff69b7cf84a9131c05be73bde525) - Initial commit [`d96cebc`](https://github.com/i18nhero/cli/commit/d96cebc79c1f5243aa1ed05b2e68aaf5e380c61a) diff --git a/Cargo.lock b/Cargo.lock index baa1186..0635470 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -87,12 +87,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "anyhow" -version = "1.0.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" - [[package]] name = "async-compression" version = "0.4.12" @@ -148,15 +142,6 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "brotli" version = "6.0.0" @@ -325,15 +310,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "cpufeatures" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.4.2" @@ -343,16 +319,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "deranged" version = "0.3.11" @@ -375,16 +341,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "dirs" version = "5.0.1" @@ -513,16 +469,6 @@ dependencies = [ "pin-utils", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -684,12 +630,10 @@ dependencies = [ "console", "dialoguer", "dirs", - "json5", "reqwest", "schemars", "serde", "serde_json", - "serde_yml", "supports-hyperlinks", "tempfile", "terminal-link", @@ -763,17 +707,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "json5" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" -dependencies = [ - "pest", - "pest_derive", - "serde", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -796,16 +729,6 @@ dependencies = [ "libc", ] -[[package]] -name = "libyml" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980" -dependencies = [ - "anyhow", - "version_check", -] - [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -926,51 +849,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "pest" -version = "2.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c73c26c01b8c87956cea613c907c9d6ecffd8d18a2a5908e5de0adfaa185cea" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664d22978e2815783adbdd2c588b455b1bd625299ce36b2a99881ac9627e6d8d" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d5487022d5d33f4c30d91c22afa240ce2a644e87fe08caad974d4eab6badbe" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0091754bbd0ea592c4deb3a122ce8ecbb0753b738aa82bc055fcc2eccc8d8174" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - [[package]] name = "pin-project" version = "1.1.5" @@ -1377,32 +1255,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yml" -version = "0.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" -dependencies = [ - "indexmap", - "itoa", - "libyml", - "memchr", - "ryu", - "serde", - "version_check", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "shell-words" version = "1.1.0" @@ -1704,18 +1556,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - [[package]] name = "unicode-bidi" version = "0.3.15" diff --git a/Cargo.toml b/Cargo.toml index a14e8cb..5d5d426 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ clap_complete = "4.5.29" console = { version = "0.15.8" } dirs = { version = "5.0.1" } dialoguer = { version = "0.11.0" } -json5 = "0.4.1" reqwest = { version = "0.12.8", default-features = false, features = [ "brotli", "charset", @@ -37,7 +36,6 @@ reqwest = { version = "0.12.8", default-features = false, features = [ schemars = "0.8.21" serde = { version = "1.0.210", features = ["derive"] } serde_json = "1.0.128" -serde_yml = "0.0.12" supports-hyperlinks = "3.0.0" tempfile = "3.13.0" terminal-link = "0.1.0" diff --git a/packages/i18nhero/Cargo.toml b/packages/i18nhero/Cargo.toml index b7da657..726a2bd 100644 --- a/packages/i18nhero/Cargo.toml +++ b/packages/i18nhero/Cargo.toml @@ -28,12 +28,10 @@ clap_complete = { workspace = true } console = { workspace = true } dialoguer = { workspace = true } dirs = { workspace = true } -json5 = { workspace = true } reqwest = { workspace = true } schemars = { workspace = true, optional = true } serde = { workspace = true } serde_json = { workspace = true } -serde_yml = { workspace = true } supports-hyperlinks = { workspace = true } terminal-link = { workspace = true } tokio = { workspace = true } diff --git a/packages/i18nhero/src/config/mod.rs b/packages/i18nhero/src/config/mod.rs index 914cfc6..c4b40d9 100644 --- a/packages/i18nhero/src/config/mod.rs +++ b/packages/i18nhero/src/config/mod.rs @@ -11,10 +11,6 @@ pub enum CliConfigOutputFormat { #[default] #[serde(rename = "json")] Json, - #[serde(rename = "json5")] - Json5, - #[serde(rename = "yaml")] - Yaml, } impl CliConfigOutputFormat { @@ -22,8 +18,6 @@ impl CliConfigOutputFormat { pub const fn to_file_ext(&self) -> &'static str { match self { Self::Json => "json", - Self::Json5 => "json5", - Self::Yaml => "yml", } } } diff --git a/packages/i18nhero/src/error/mod.rs b/packages/i18nhero/src/error/mod.rs index a7c54d6..9612977 100644 --- a/packages/i18nhero/src/error/mod.rs +++ b/packages/i18nhero/src/error/mod.rs @@ -1,12 +1,6 @@ #[derive(Debug)] pub enum CliError { Io(std::io::Error), - SerializeJson(serde_json::Error), - SerializeJson5(json5::Error), - SerializeYml(serde_yml::Error), - DeserializeJson(serde_json::Error), - DeserializeJson5(json5::Error), - DeserializeYml(serde_yml::Error), PushLocaleHttp(reqwest::Error), PullLocaleHttp(reqwest::Error), ConfigAlreadyExists, @@ -49,12 +43,6 @@ impl core::fmt::Display for CliError { Self::ConfigLoad(e) => write!(f, "Error loading config - {e}"), Self::ConfigSave(e) => write!(f, "Error saving config - {e}"), Self::ConfigParse(e) => write!(f, "Error parsing config - {e}"), - Self::SerializeJson(e) => write!(f, "Error serializing file - {e}"), - Self::SerializeJson5(e) => write!(f, "Error serializing file - {e}"), - Self::SerializeYml(e) => write!(f, "Error serializing file - {e}"), - Self::DeserializeJson(e) => write!(f, "Error deserializing file - {e}"), - Self::DeserializeJson5(e) => write!(f, "Error deserializing file - {e}"), - Self::DeserializeYml(e) => write!(f, "Error deserializing file - {e}"), Self::ConfigSerialize(e) => write!(f, "Error serializing config - {e}"), Self::AuthConfigSerialize(e) => write!(f, "Error serializing auth config - {e}"), Self::AuthConfigDeserialize(e) => write!(f, "Error deserializing auth config - {e}"), diff --git a/packages/i18nhero/src/generators/mod.rs b/packages/i18nhero/src/generators/mod.rs deleted file mode 100644 index fb85b47..0000000 --- a/packages/i18nhero/src/generators/mod.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::{config::CliConfigOutputFormat, error::CliError}; - -#[inline] -pub fn parse_input( - format: &CliConfigOutputFormat, - contents: &str, -) -> Result, CliError> { - match format { - CliConfigOutputFormat::Json => { - serde_json::from_str(contents).map_err(CliError::DeserializeJson) - } - CliConfigOutputFormat::Json5 => { - json5::from_str(contents).map_err(CliError::DeserializeJson5) - } - CliConfigOutputFormat::Yaml => { - serde_yml::from_str(contents).map_err(CliError::DeserializeYml) - } - } -} - -#[inline] -pub fn stringify( - format: &CliConfigOutputFormat, - translations: &std::collections::BTreeMap, -) -> Result { - match format { - CliConfigOutputFormat::Json => { - serde_json::to_string_pretty(&translations).map_err(CliError::SerializeJson) - } - CliConfigOutputFormat::Json5 => { - json5::to_string(&translations).map_err(CliError::SerializeJson5) - } - CliConfigOutputFormat::Yaml => { - serde_yml::to_string(&translations).map_err(CliError::SerializeYml) - } - } - .map(|output| { - let mut trimmed = output.trim().to_string(); - trimmed.push('\n'); - trimmed - }) -} diff --git a/packages/i18nhero/src/main.rs b/packages/i18nhero/src/main.rs index 0adbe23..bf786db 100644 --- a/packages/i18nhero/src/main.rs +++ b/packages/i18nhero/src/main.rs @@ -8,7 +8,6 @@ mod commands; mod completions; mod config; mod error; -mod generators; mod init; mod pull; mod push; @@ -43,10 +42,11 @@ async fn _main() -> Result<(), CliError> { } #[tokio::main] +#[expect(clippy::needless_return)] async fn main() { if let Err(error) = _main().await { terminal::print_error(&error); - std::process::exit(1) + std::process::exit(1); } } diff --git a/packages/i18nhero/src/pull/mod.rs b/packages/i18nhero/src/pull/mod.rs index 3462112..e946bb4 100644 --- a/packages/i18nhero/src/pull/mod.rs +++ b/packages/i18nhero/src/pull/mod.rs @@ -1,8 +1,8 @@ use crate::{ + auth::AuthConfig, commands::pull::PullCommandArguments, config::{CliConfig, CliConfigOutputFormat}, error::CliError, - generators, terminal::print_saving_file, DEFAULT_WEB_API_HOST, }; @@ -13,14 +13,21 @@ struct PullLocale { country_code: Option, - translations: std::collections::BTreeMap, + content: String, } #[inline] -async fn fetch_locales(host: &str, project_id: &str) -> Result, CliError> { - let url = format!("{host}/projects/{project_id}/pull"); - - reqwest::get(url) +async fn fetch_locales( + api_key: &str, + host: &str, + project_id: &str, +) -> Result, CliError> { + let client = reqwest::Client::new(); + + client + .get(format!("{host}/projects/{project_id}/pull")) + .header("x-api-key", api_key) + .send() .await .map_err(CliError::PullLocaleHttp)? .error_for_status() @@ -57,11 +64,9 @@ async fn save_locales(config: &CliConfig, locales: Vec) -> Result<() print_saving_file(&file_name); - let contents = generators::stringify(&config.output.format, &locale.translations)?; - tokio::fs::write( config.output.path.join(file_name), - format!("{}\n", contents.trim()), + format!("{}\n", locale.content.trim()), ) .await .map_err(CliError::LocaleSave)?; @@ -76,7 +81,10 @@ pub async fn run(arguments: &PullCommandArguments, config: &CliConfig) -> Result return Err(CliError::MissingProjectId); } - let mut locales = fetch_locales( + let auth = AuthConfig::load()?; + + let locales = fetch_locales( + &auth.api_key, arguments .api_host .as_ref() @@ -85,12 +93,5 @@ pub async fn run(arguments: &PullCommandArguments, config: &CliConfig) -> Result ) .await?; - // TODO: move to api - if !config.output.save_missing_values { - for locale in &mut locales { - locale.translations.retain(|_, v| !v.is_empty()); - } - } - save_locales(config, locales).await } diff --git a/packages/i18nhero/src/push/mod.rs b/packages/i18nhero/src/push/mod.rs index d9dc4f2..32241f6 100644 --- a/packages/i18nhero/src/push/mod.rs +++ b/packages/i18nhero/src/push/mod.rs @@ -1,4 +1,5 @@ use crate::{ + auth::AuthConfig, commands::push::PushCommandArguments, config::{CliConfig, CliConfigOutputFormat}, error::CliError, @@ -9,7 +10,9 @@ use crate::{ struct PushLocale { file_name: String, - translations: std::collections::HashMap, + file_format: String, + + content: String, } #[inline] @@ -28,11 +31,10 @@ fn read_locales( if let Some(stem) = p.file_stem() { let raw = std::fs::read_to_string(&p).map_err(CliError::LocaleRead)?; - let translations = crate::generators::parse_input(file_format, &raw)?; - let locale = PushLocale { file_name: stem.to_string_lossy().to_string(), - translations, + file_format: expected_file_ext.to_string(), + content: raw, }; locales.push(locale); @@ -45,16 +47,16 @@ fn read_locales( #[inline] async fn upload_locales( + api_key: &str, host: &str, project_id: &str, locales: &[PushLocale], ) -> Result<(), CliError> { let client = reqwest::Client::new(); - let url = format!("{host}/projects/{project_id}/push"); - client - .put(url) + .put(format!("{host}/projects/{project_id}/push")) + .header("x-api-key", api_key) .json(locales) .send() .await @@ -70,7 +72,10 @@ pub async fn run(arguments: &PushCommandArguments, config: &CliConfig) -> Result let locales = read_locales(&config.output.path, &config.output.format)?; if !locales.is_empty() { + let auth = AuthConfig::load()?; + upload_locales( + &auth.api_key, arguments .api_host .as_ref()