Reformat project

This commit is contained in:
Gregory Schier
2025-12-13 08:10:12 -08:00
parent c20c0eff32
commit cfbfd66eef
68 changed files with 290 additions and 759 deletions
+1
View File
@@ -5,3 +5,4 @@ chain_width = 100
max_width = 100 max_width = 100
single_line_if_else_max_width = 100 single_line_if_else_max_width = 100
fn_call_width = 100 fn_call_width = 100
struct_lit_width = 100
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::error::Result; use crate::error::Result;
use tauri::{command, AppHandle, Manager, Runtime, State, WebviewWindow}; use tauri::{AppHandle, Manager, Runtime, State, WebviewWindow, command};
use tauri_plugin_dialog::{DialogExt, MessageDialogKind}; use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
use yaak_crypto::manager::EncryptionManagerExt; use yaak_crypto::manager::EncryptionManagerExt;
use yaak_plugins::events::{GetThemesResponse, PluginContext}; use yaak_plugins::events::{GetThemesResponse, PluginContext};
+1 -1
View File
@@ -1,4 +1,4 @@
use mime_guess::{mime, Mime}; use mime_guess::{Mime, mime};
use std::path::Path; use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use tokio::fs; use tokio::fs;
+1 -1
View File
@@ -1,5 +1,5 @@
use std::io;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use std::io;
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
+2 -10
View File
@@ -100,9 +100,7 @@ pub async fn send_http_request_with_context<R: Runtime>(
let cb = PluginTemplateCallback::new(window.app_handle(), &plugin_context, RenderPurpose::Send); let cb = PluginTemplateCallback::new(window.app_handle(), &plugin_context, RenderPurpose::Send);
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
let request = match render_http_request(&resolved_request, environment_chain, &cb, &opt).await { let request = match render_http_request(&resolved_request, environment_chain, &cb, &opt).await {
Ok(r) => r, Ok(r) => r,
@@ -127,13 +125,7 @@ pub async fn send_http_request_with_context<R: Runtime>(
let proxy_setting = match settings.proxy { let proxy_setting = match settings.proxy {
None => HttpConnectionProxySetting::System, None => HttpConnectionProxySetting::System,
Some(ProxySetting::Disabled) => HttpConnectionProxySetting::Disabled, Some(ProxySetting::Disabled) => HttpConnectionProxySetting::Disabled,
Some(ProxySetting::Enabled { Some(ProxySetting::Enabled { http, https, auth, bypass, disabled }) => {
http,
https,
auth,
bypass,
disabled,
}) => {
if disabled { if disabled {
HttpConnectionProxySetting::System HttpConnectionProxySetting::System
} else { } else {
+8 -30
View File
@@ -180,9 +180,7 @@ async fn cmd_grpc_reflect<R: Runtime>(
&PluginContext::new(&window), &PluginContext::new(&window),
RenderPurpose::Send, RenderPurpose::Send,
), ),
&RenderOptions { &RenderOptions { error_behavior: RenderErrorBehavior::Throw },
error_behavior: RenderErrorBehavior::Throw,
},
) )
.await?; .await?;
@@ -234,9 +232,7 @@ async fn cmd_grpc_go<R: Runtime>(
&PluginContext::new(&window), &PluginContext::new(&window),
RenderPurpose::Send, RenderPurpose::Send,
), ),
&RenderOptions { &RenderOptions { error_behavior: RenderErrorBehavior::Throw },
error_behavior: RenderErrorBehavior::Throw,
},
) )
.await?; .await?;
@@ -362,9 +358,7 @@ async fn cmd_grpc_go<R: Runtime>(
&PluginContext::new(&window), &PluginContext::new(&window),
RenderPurpose::Send, RenderPurpose::Send,
), ),
&RenderOptions { &RenderOptions { error_behavior: RenderErrorBehavior::Throw },
error_behavior: RenderErrorBehavior::Throw,
},
) )
.await .await
.expect("Failed to render template") .expect("Failed to render template")
@@ -414,9 +408,7 @@ async fn cmd_grpc_go<R: Runtime>(
&PluginContext::new(&window), &PluginContext::new(&window),
RenderPurpose::Send, RenderPurpose::Send,
), ),
&RenderOptions { &RenderOptions { error_behavior: RenderErrorBehavior::Throw },
error_behavior: RenderErrorBehavior::Throw,
},
) )
.await?; .await?;
@@ -813,10 +805,7 @@ async fn cmd_http_response_body<R: Runtime>(
Some(filter) if !filter.is_empty() => { Some(filter) if !filter.is_empty() => {
Ok(plugin_manager.filter_data(&window, filter, &body, content_type).await?) Ok(plugin_manager.filter_data(&window, filter, &body, content_type).await?)
} }
_ => Ok(FilterResponse { _ => Ok(FilterResponse { content: body, error: None }),
content: body,
error: None,
}),
} }
} }
@@ -1202,11 +1191,7 @@ async fn cmd_install_plugin<R: Runtime>(
plugin_manager.add_plugin_by_dir(&PluginContext::new(&window), &directory).await?; plugin_manager.add_plugin_by_dir(&PluginContext::new(&window), &directory).await?;
Ok(app_handle.db().upsert_plugin( Ok(app_handle.db().upsert_plugin(
&Plugin { &Plugin { directory: directory.into(), url, ..Default::default() },
directory: directory.into(),
url,
..Default::default()
},
&UpdateSource::from_window(&window), &UpdateSource::from_window(&window),
)?) )?)
} }
@@ -1527,11 +1512,7 @@ pub fn run() {
let _ = db.cancel_pending_websocket_connections(); let _ = db.cancel_pending_websocket_connections();
}); });
} }
RunEvent::WindowEvent { RunEvent::WindowEvent { event: WindowEvent::Focused(true), label, .. } => {
event: WindowEvent::Focused(true),
label,
..
} => {
if cfg!(feature = "updater") { if cfg!(feature = "updater") {
// Run update check whenever the window is focused // Run update check whenever the window is focused
let w = app_handle.get_webview_window(&label).unwrap(); let w = app_handle.get_webview_window(&label).unwrap();
@@ -1566,10 +1547,7 @@ pub fn run() {
} }
}); });
} }
RunEvent::WindowEvent { RunEvent::WindowEvent { event: WindowEvent::CloseRequested { .. }, .. } => {
event: WindowEvent::CloseRequested { .. },
..
} => {
if let Err(e) = app_handle.save_window_state(StateFlags::all()) { if let Err(e) = app_handle.save_window_state(StateFlags::all()) {
warn!("Failed to save window state {e:?}"); warn!("Failed to save window state {e:?}");
} else { } else {
+3 -9
View File
@@ -78,9 +78,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
environment_id.as_deref(), environment_id.as_deref(),
)?; )?;
let cb = PluginTemplateCallback::new(app_handle, &plugin_context, req.purpose); let cb = PluginTemplateCallback::new(app_handle, &plugin_context, req.purpose);
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
let grpc_request = let grpc_request =
render_grpc_request(&req.grpc_request, environment_chain, &cb, &opt).await?; render_grpc_request(&req.grpc_request, environment_chain, &cb, &opt).await?;
Ok(Some(InternalEventPayload::RenderGrpcRequestResponse(RenderGrpcRequestResponse { Ok(Some(InternalEventPayload::RenderGrpcRequestResponse(RenderGrpcRequestResponse {
@@ -99,9 +97,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
environment_id.as_deref(), environment_id.as_deref(),
)?; )?;
let cb = PluginTemplateCallback::new(app_handle, &plugin_context, req.purpose); let cb = PluginTemplateCallback::new(app_handle, &plugin_context, req.purpose);
let opt = &RenderOptions { let opt = &RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
let http_request = let http_request =
render_http_request(&req.http_request, environment_chain, &cb, &opt).await?; render_http_request(&req.http_request, environment_chain, &cb, &opt).await?;
Ok(Some(InternalEventPayload::RenderHttpRequestResponse(RenderHttpRequestResponse { Ok(Some(InternalEventPayload::RenderHttpRequestResponse(RenderHttpRequestResponse {
@@ -130,9 +126,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
environment_id.as_deref(), environment_id.as_deref(),
)?; )?;
let cb = PluginTemplateCallback::new(app_handle, &plugin_context, req.purpose); let cb = PluginTemplateCallback::new(app_handle, &plugin_context, req.purpose);
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
let data = render_json_value(req.data, environment_chain, &cb, &opt).await?; let data = render_json_value(req.data, environment_chain, &cb, &opt).await?;
Ok(Some(InternalEventPayload::TemplateRenderResponse(TemplateRenderResponse { data }))) Ok(Some(InternalEventPayload::TemplateRenderResponse(TemplateRenderResponse { data })))
} }
+2 -14
View File
@@ -80,12 +80,7 @@ pub async fn render_grpc_request<T: TemplateCallback>(
let url = parse_and_render(r.url.as_str(), vars, cb, &opt).await?; let url = parse_and_render(r.url.as_str(), vars, cb, &opt).await?;
Ok(GrpcRequest { Ok(GrpcRequest { url, metadata, authentication, ..r.to_owned() })
url,
metadata,
authentication,
..r.to_owned()
})
} }
pub async fn render_http_request<T: TemplateCallback>( pub async fn render_http_request<T: TemplateCallback>(
@@ -164,12 +159,5 @@ pub async fn render_http_request<T: TemplateCallback>(
// This doesn't fit perfectly with the concept of "rendering" but it kind of does // This doesn't fit perfectly with the concept of "rendering" but it kind of does
let (url, url_parameters) = apply_path_placeholders(&url, url_parameters); let (url, url_parameters) = apply_path_placeholders(&url, url_parameters);
Ok(HttpRequest { Ok(HttpRequest { url, url_parameters, headers, body, authentication, ..r.to_owned() })
url,
url_parameters,
headers,
body,
authentication,
..r.to_owned()
})
} }
+3 -9
View File
@@ -259,17 +259,11 @@ async fn start_integrated_update<R: Runtime>(
self.win.unlisten(self.id); self.win.unlisten(self.id);
} }
} }
let _guard = Unlisten { let _guard = Unlisten { win: window, id: event_id };
win: window,
id: event_id,
};
// 2) Emit the event now that listener is in place // 2) Emit the event now that listener is in place
let info = UpdateInfo { let info =
version: update.version.to_string(), UpdateInfo { version: update.version.to_string(), downloaded, reply_event_id: reply_id };
downloaded,
reply_event_id: reply_id,
};
window window
.emit_to(window.label(), "update_available", &info) .emit_to(window.label(), "update_available", &info)
.map_err(|e| GenericError(format!("Failed to emit update_available: {e}")))?; .map_err(|e| GenericError(format!("Failed to emit update_available: {e}")))?;
+2 -1
View File
@@ -3,7 +3,8 @@ use crate::window_menu::app_menu;
use log::{info, warn}; use log::{info, warn};
use rand::random; use rand::random;
use tauri::{ use tauri::{
AppHandle, Emitter, LogicalSize, Manager, PhysicalSize, Runtime, WebviewUrl, WebviewWindow, WindowEvent AppHandle, Emitter, LogicalSize, Manager, PhysicalSize, Runtime, WebviewUrl, WebviewWindow,
WindowEvent,
}; };
use tauri_plugin_opener::OpenerExt; use tauri_plugin_opener::OpenerExt;
use tokio::sync::mpsc; use tokio::sync::mpsc;
+9 -4
View File
@@ -30,7 +30,8 @@ pub fn app_menu<R: Runtime>(app_handle: &AppHandle<R>) -> tauri::Result<Menu<R>>
], ],
)?; )?;
#[cfg(target_os = "macos")] { #[cfg(target_os = "macos")]
{
window_menu.set_as_windows_menu_for_nsapp()?; window_menu.set_as_windows_menu_for_nsapp()?;
} }
@@ -48,7 +49,8 @@ pub fn app_menu<R: Runtime>(app_handle: &AppHandle<R>) -> tauri::Result<Menu<R>>
], ],
)?; )?;
#[cfg(target_os = "macos")] { #[cfg(target_os = "macos")]
{
help_menu.set_as_windows_menu_for_nsapp()?; help_menu.set_as_windows_menu_for_nsapp()?;
} }
@@ -151,8 +153,11 @@ pub fn app_menu<R: Runtime>(app_handle: &AppHandle<R>) -> tauri::Result<Menu<R>>
.build(app_handle)?, .build(app_handle)?,
&MenuItemBuilder::with_id("dev.reset_size".to_string(), "Reset Size") &MenuItemBuilder::with_id("dev.reset_size".to_string(), "Reset Size")
.build(app_handle)?, .build(app_handle)?,
&MenuItemBuilder::with_id("dev.reset_size_record".to_string(), "Reset Size 16x9") &MenuItemBuilder::with_id(
.build(app_handle)?, "dev.reset_size_record".to_string(),
"Reset Size 16x9",
)
.build(app_handle)?,
&MenuItemBuilder::with_id( &MenuItemBuilder::with_id(
"dev.generate_theme_css".to_string(), "dev.generate_theme_css".to_string(),
"Generate Theme CSS", "Generate Theme CSS",
+2 -2
View File
@@ -1,4 +1,4 @@
pub mod window;
pub mod platform;
pub mod api_client; pub mod api_client;
pub mod error; pub mod error;
pub mod platform;
pub mod window;
+2 -8
View File
@@ -96,18 +96,12 @@ impl EncryptionManager {
let workspace = tx.get_workspace(workspace_id)?; let workspace = tx.get_workspace(workspace_id)?;
let workspace_meta = tx.get_or_create_workspace_meta(workspace_id)?; let workspace_meta = tx.get_or_create_workspace_meta(workspace_id)?;
tx.upsert_workspace( tx.upsert_workspace(
&Workspace { &Workspace { encryption_key_challenge, ..workspace },
encryption_key_challenge,
..workspace
},
&UpdateSource::Background, &UpdateSource::Background,
)?; )?;
Ok(tx.upsert_workspace_meta( Ok(tx.upsert_workspace_meta(
&WorkspaceMeta { &WorkspaceMeta { encryption_key: Some(encrypted_key.clone()), ..workspace_meta },
encryption_key: Some(encrypted_key.clone()),
..workspace_meta
},
&UpdateSource::Background, &UpdateSource::Background,
)?) )?)
})?; })?;
+1 -3
View File
@@ -39,9 +39,7 @@ impl WorkspaceKey {
} }
pub(crate) fn from_raw_key(key: &[u8]) -> Self { pub(crate) fn from_raw_key(key: &[u8]) -> Self {
Self { Self { key: Key::<XChaCha20Poly1305>::clone_from_slice(key) }
key: Key::<XChaCha20Poly1305>::clone_from_slice(key),
}
} }
pub(crate) fn raw_key(&self) -> &[u8] { pub(crate) fn raw_key(&self) -> &[u8] {
+1 -4
View File
@@ -34,8 +34,5 @@ pub(crate) async fn list() -> Result<Fonts> {
ui_fonts.sort(); ui_fonts.sort();
editor_fonts.sort(); editor_fonts.sort();
Ok(Fonts { Ok(Fonts { ui_fonts, editor_fonts })
ui_fonts,
editor_fonts,
})
} }
+2 -2
View File
@@ -1,10 +1,10 @@
use crate::error::Result;
use std::path::Path; use std::path::Path;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use crate::error::Result;
use crate::error::Error::GitNotFound;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt; use std::os::windows::process::CommandExt;
use crate::error::Error::GitNotFound;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
const CREATE_NO_WINDOW: u32 = 0x0800_0000; const CREATE_NO_WINDOW: u32 = 0x0800_0000;
+5 -2
View File
@@ -1,4 +1,7 @@
use crate::commands::{add, add_credential, add_remote, branch, checkout, commit, delete_branch, fetch_all, initialize, log, merge_branch, pull, push, remotes, rm_remote, status, unstage}; use crate::commands::{
add, add_credential, add_remote, branch, checkout, commit, delete_branch, fetch_all,
initialize, log, merge_branch, pull, push, remotes, rm_remote, status, unstage,
};
use tauri::{ use tauri::{
Runtime, generate_handler, Runtime, generate_handler,
plugin::{Builder, TauriPlugin}, plugin::{Builder, TauriPlugin},
@@ -10,6 +13,7 @@ mod branch;
mod commands; mod commands;
mod commit; mod commit;
mod credential; mod credential;
pub mod error;
mod fetch; mod fetch;
mod init; mod init;
mod log; mod log;
@@ -21,7 +25,6 @@ mod repository;
mod status; mod status;
mod unstage; mod unstage;
mod util; mod util;
pub mod error;
pub fn init<R: Runtime>() -> TauriPlugin<R> { pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::new("yaak-git") Builder::new("yaak-git")
+2 -7
View File
@@ -37,10 +37,7 @@ pub(crate) fn git_pull(dir: &Path) -> Result<PullResult> {
info!("Pulled status={} {combined}", out.status); info!("Pulled status={} {combined}", out.status);
if combined.to_lowercase().contains("could not read") { if combined.to_lowercase().contains("could not read") {
return Ok(PullResult::NeedsCredentials { return Ok(PullResult::NeedsCredentials { url: remote_url.to_string(), error: None });
url: remote_url.to_string(),
error: None,
});
} }
if combined.to_lowercase().contains("unable to access") { if combined.to_lowercase().contains("unable to access") {
@@ -58,9 +55,7 @@ pub(crate) fn git_pull(dir: &Path) -> Result<PullResult> {
return Ok(PullResult::UpToDate); return Ok(PullResult::UpToDate);
} }
Ok(PullResult::Success { Ok(PullResult::Success { message: format!("Pulled from {}/{}", remote_name, branch_name) })
message: format!("Pulled from {}/{}", remote_name, branch_name),
})
} }
// pub(crate) fn git_pull_old(dir: &Path) -> Result<PullResult> { // pub(crate) fn git_pull_old(dir: &Path) -> Result<PullResult> {
+2 -7
View File
@@ -37,10 +37,7 @@ pub(crate) fn git_push(dir: &Path) -> Result<PushResult> {
info!("Pushed to repo status={} {combined}", out.status); info!("Pushed to repo status={} {combined}", out.status);
if combined.to_lowercase().contains("could not read") { if combined.to_lowercase().contains("could not read") {
return Ok(PushResult::NeedsCredentials { return Ok(PushResult::NeedsCredentials { url: remote_url.to_string(), error: None });
url: remote_url.to_string(),
error: None,
});
} }
if combined.to_lowercase().contains("unable to access") { if combined.to_lowercase().contains("unable to access") {
@@ -58,7 +55,5 @@ pub(crate) fn git_push(dir: &Path) -> Result<PushResult> {
return Err(GenericError(format!("Failed to push {combined}"))); return Err(GenericError(format!("Failed to push {combined}")));
} }
Ok(PushResult::Success { Ok(PushResult::Success { message: format!("Pushed to {}/{}", remote_name, branch_name) })
message: format!("Pushed to {}/{}", remote_name, branch_name),
})
} }
+2 -8
View File
@@ -28,10 +28,7 @@ pub(crate) fn git_remotes(dir: &Path) -> Result<Vec<GitRemote>> {
continue; continue;
} }
}; };
remotes.push(GitRemote { remotes.push(GitRemote { name: name.to_string(), url: r.url().map(|u| u.to_string()) });
name: name.to_string(),
url: r.url().map(|u| u.to_string()),
});
} }
Ok(remotes) Ok(remotes)
@@ -40,10 +37,7 @@ pub(crate) fn git_remotes(dir: &Path) -> Result<Vec<GitRemote>> {
pub(crate) fn git_add_remote(dir: &Path, name: &str, url: &str) -> Result<GitRemote> { pub(crate) fn git_add_remote(dir: &Path, name: &str, url: &str) -> Result<GitRemote> {
let repo = open_repo(dir)?; let repo = open_repo(dir)?;
repo.remote(name, url)?; repo.remote(name, url)?;
Ok(GitRemote { Ok(GitRemote { name: name.to_string(), url: Some(url.to_string()) })
name: name.to_string(),
url: Some(url.to_string()),
})
} }
pub(crate) fn git_rm_remote(dir: &Path, name: &str) -> Result<()> { pub(crate) fn git_rm_remote(dir: &Path, name: &str) -> Result<()> {
+1 -2
View File
@@ -1,5 +1,5 @@
use std::path::Path;
use crate::error::Error::{GitRepoNotFound, GitUnknown}; use crate::error::Error::{GitRepoNotFound, GitUnknown};
use std::path::Path;
pub(crate) fn open_repo(dir: &Path) -> crate::error::Result<git2::Repository> { pub(crate) fn open_repo(dir: &Path) -> crate::error::Result<git2::Repository> {
match git2::Repository::discover(dir) { match git2::Repository::discover(dir) {
@@ -8,4 +8,3 @@ pub(crate) fn open_repo(dir: &Path) -> crate::error::Result<git2::Repository> {
Err(e) => Err(GitUnknown(e)), Err(e) => Err(GitUnknown(e)),
} }
} }
+2 -3
View File
@@ -1,6 +1,6 @@
use std::path::Path;
use log::info;
use crate::repository::open_repo; use crate::repository::open_repo;
use log::info;
use std::path::Path;
pub(crate) fn git_unstage(dir: &Path, rela_path: &Path) -> crate::error::Result<()> { pub(crate) fn git_unstage(dir: &Path, rela_path: &Path) -> crate::error::Result<()> {
let repo = open_repo(dir)?; let repo = open_repo(dir)?;
@@ -25,4 +25,3 @@ pub(crate) fn git_unstage(dir: &Path, rela_path: &Path) -> crate::error::Result<
Ok(()) Ok(())
} }
+3 -12
View File
@@ -42,11 +42,7 @@ impl AutoReflectionClient {
get_transport(validate_certificates, client_cert.clone())?, get_transport(validate_certificates, client_cert.clone())?,
uri.clone(), uri.clone(),
); );
Ok(AutoReflectionClient { Ok(AutoReflectionClient { use_v1alpha: false, client_v1, client_v1alpha })
use_v1alpha: false,
client_v1,
client_v1alpha,
})
} }
#[async_recursion] #[async_recursion]
@@ -140,9 +136,7 @@ fn to_v1_msg_response(
service: v service: v
.service .service
.iter() .iter()
.map(|s| ServiceResponse { .map(|s| ServiceResponse { name: s.name.clone() })
name: s.name.clone(),
})
.collect(), .collect(),
}) })
} }
@@ -176,10 +170,7 @@ fn to_v1alpha_msg_request(
extension_number, extension_number,
containing_type, containing_type,
}) => v1alpha::server_reflection_request::MessageRequest::FileContainingExtension( }) => v1alpha::server_reflection_request::MessageRequest::FileContainingExtension(
v1alpha::ExtensionRequest { v1alpha::ExtensionRequest { extension_number, containing_type },
extension_number,
containing_type,
},
), ),
MessageRequest::AllExtensionNumbersOfType(v) => { MessageRequest::AllExtensionNumbersOfType(v) => {
v1alpha::server_reflection_request::MessageRequest::AllExtensionNumbersOfType(v) v1alpha::server_reflection_request::MessageRequest::AllExtensionNumbersOfType(v)
+1 -1
View File
@@ -1,7 +1,7 @@
use prost_reflect::prost::Message; use prost_reflect::prost::Message;
use prost_reflect::{DynamicMessage, MethodDescriptor}; use prost_reflect::{DynamicMessage, MethodDescriptor};
use tonic::codec::{Codec, DecodeBuf, Decoder, EncodeBuf, Encoder};
use tonic::Status; use tonic::Status;
use tonic::codec::{Codec, DecodeBuf, Decoder, EncodeBuf, Encoder};
#[derive(Clone)] #[derive(Clone)]
pub struct DynamicCodec(MethodDescriptor); pub struct DynamicCodec(MethodDescriptor);
+1 -1
View File
@@ -1,8 +1,8 @@
use crate::manager::GrpcStreamError; use crate::manager::GrpcStreamError;
use prost::DecodeError;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use serde_json::Error as SerdeJsonError; use serde_json::Error as SerdeJsonError;
use std::io; use std::io;
use prost::DecodeError;
use thiserror::Error; use thiserror::Error;
use tonic::Status; use tonic::Status;
+9 -33
View File
@@ -11,9 +11,7 @@ struct JsonSchemaGenerator {
impl JsonSchemaGenerator { impl JsonSchemaGenerator {
pub fn new() -> Self { pub fn new() -> Self {
JsonSchemaGenerator { JsonSchemaGenerator { msg_mapping: HashMap::new() }
msg_mapping: HashMap::new(),
}
} }
pub fn generate_json_schema(msg: MessageDescriptor) -> JsonSchemaEntry { pub fn generate_json_schema(msg: MessageDescriptor) -> JsonSchemaEntry {
@@ -297,16 +295,10 @@ impl JsonSchemaEntry {
impl JsonSchemaEntry { impl JsonSchemaEntry {
pub fn object() -> Self { pub fn object() -> Self {
JsonSchemaEntry { JsonSchemaEntry { type_: Some(JsonType::Object), ..Default::default() }
type_: Some(JsonType::Object),
..Default::default()
}
} }
pub fn boolean() -> Self { pub fn boolean() -> Self {
JsonSchemaEntry { JsonSchemaEntry { type_: Some(JsonType::Boolean), ..Default::default() }
type_: Some(JsonType::Boolean),
..Default::default()
}
} }
pub fn number<S: Into<String>>(format: S) -> Self { pub fn number<S: Into<String>>(format: S) -> Self {
JsonSchemaEntry { JsonSchemaEntry {
@@ -316,10 +308,7 @@ impl JsonSchemaEntry {
} }
} }
pub fn string() -> Self { pub fn string() -> Self {
JsonSchemaEntry { JsonSchemaEntry { type_: Some(JsonType::String), ..Default::default() }
type_: Some(JsonType::String),
..Default::default()
}
} }
pub fn string_with_format<S: Into<String>>(format: S) -> Self { pub fn string_with_format<S: Into<String>>(format: S) -> Self {
@@ -330,16 +319,10 @@ impl JsonSchemaEntry {
} }
} }
pub fn reference<S: AsRef<str>>(ref_: S) -> Self { pub fn reference<S: AsRef<str>>(ref_: S) -> Self {
JsonSchemaEntry { JsonSchemaEntry { ref_: Some(format!("#/$defs/{}", ref_.as_ref())), ..Default::default() }
ref_: Some(format!("#/$defs/{}", ref_.as_ref())),
..Default::default()
}
} }
pub fn root_reference() -> Self{ pub fn root_reference() -> Self {
JsonSchemaEntry { JsonSchemaEntry { ref_: Some("#".to_string()), ..Default::default() }
ref_: Some("#".to_string()),
..Default::default()
}
} }
pub fn array(item: JsonSchemaEntry) -> Self { pub fn array(item: JsonSchemaEntry) -> Self {
JsonSchemaEntry { JsonSchemaEntry {
@@ -349,11 +332,7 @@ impl JsonSchemaEntry {
} }
} }
pub fn enums(enums: Vec<String>) -> Self { pub fn enums(enums: Vec<String>) -> Self {
JsonSchemaEntry { JsonSchemaEntry { type_: Some(JsonType::String), enum_: Some(enums), ..Default::default() }
type_: Some(JsonType::String),
enum_: Some(enums),
..Default::default()
}
} }
pub fn map(value_type: JsonSchemaEntry) -> Self { pub fn map(value_type: JsonSchemaEntry) -> Self {
@@ -365,10 +344,7 @@ impl JsonSchemaEntry {
} }
pub fn null() -> Self { pub fn null() -> Self {
JsonSchemaEntry { JsonSchemaEntry { type_: Some(JsonType::Null), ..Default::default() }
type_: Some(JsonType::Null),
..Default::default()
}
} }
} }
+3 -3
View File
@@ -2,17 +2,17 @@ use prost_reflect::{DynamicMessage, MethodDescriptor, SerializeOptions};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Deserializer; use serde_json::Deserializer;
mod any;
mod client; mod client;
mod codec; mod codec;
pub mod error;
mod json_schema; mod json_schema;
pub mod manager; pub mod manager;
mod reflection; mod reflection;
mod transport; mod transport;
mod any;
pub mod error;
pub use tonic::metadata::*;
pub use tonic::Code; pub use tonic::Code;
pub use tonic::metadata::*;
pub fn serialize_options() -> SerializeOptions { pub fn serialize_options() -> SerializeOptions {
SerializeOptions::new().skip_default_fields(false) SerializeOptions::new().skip_default_fields(false)
+10 -26
View File
@@ -57,19 +57,13 @@ impl Display for GrpcStreamError {
impl From<String> for GrpcStreamError { impl From<String> for GrpcStreamError {
fn from(value: String) -> Self { fn from(value: String) -> Self {
GrpcStreamError { GrpcStreamError { message: value.to_string(), status: None }
message: value.to_string(),
status: None,
}
} }
} }
impl From<Status> for GrpcStreamError { impl From<Status> for GrpcStreamError {
fn from(s: Status) -> Self { fn from(s: Status) -> Self {
GrpcStreamError { GrpcStreamError { message: s.message().to_string(), status: Some(s) }
message: s.message().to_string(),
status: Some(s),
}
} }
} }
@@ -227,10 +221,10 @@ impl GrpcConnection {
decorate_req(metadata, &mut req)?; decorate_req(metadata, &mut req)?;
client.ready().await.map_err(|e| GenericError(format!("Failed to connect: {}", e)))?; client.ready().await.map_err(|e| GenericError(format!("Failed to connect: {}", e)))?;
Ok(client.client_streaming(req, path, codec).await.map_err(|e| GrpcStreamError { Ok(client
message: e.message().to_string(), .client_streaming(req, path, codec)
status: Some(e), .await
})?) .map_err(|e| GrpcStreamError { message: e.message().to_string(), status: Some(e) })?)
} }
pub async fn server_streaming( pub async fn server_streaming(
@@ -267,10 +261,7 @@ pub struct GrpcHandle {
impl GrpcHandle { impl GrpcHandle {
pub fn new(app_handle: &AppHandle) -> Self { pub fn new(app_handle: &AppHandle) -> Self {
let pools = BTreeMap::new(); let pools = BTreeMap::new();
Self { Self { pools, app_handle: app_handle.clone() }
pools,
app_handle: app_handle.clone(),
}
} }
} }
@@ -335,10 +326,8 @@ impl GrpcHandle {
fn services_from_pool(&self, pool: &DescriptorPool) -> Vec<ServiceDefinition> { fn services_from_pool(&self, pool: &DescriptorPool) -> Vec<ServiceDefinition> {
pool.services() pool.services()
.map(|s| { .map(|s| {
let mut def = ServiceDefinition { let mut def =
name: s.full_name().to_string(), ServiceDefinition { name: s.full_name().to_string(), methods: vec![] };
methods: vec![],
};
for method in s.methods() { for method in s.methods() {
let input_message = method.input(); let input_message = method.input();
def.methods.push(MethodDefinition { def.methods.push(MethodDefinition {
@@ -384,12 +373,7 @@ impl GrpcHandle {
.clone(); .clone();
let uri = uri_from_str(uri)?; let uri = uri_from_str(uri)?;
let conn = get_transport(validate_certificates, client_cert.clone())?; let conn = get_transport(validate_certificates, client_cert.clone())?;
Ok(GrpcConnection { Ok(GrpcConnection { pool: Arc::new(RwLock::new(pool)), use_reflection, conn, uri })
pool: Arc::new(RwLock::new(pool)),
use_reflection,
conn,
uri,
})
} }
fn get_pool(&self, id: &str, uri: &str, proto_files: &Vec<PathBuf>) -> Option<&DescriptorPool> { fn get_pool(&self, id: &str, uri: &str, proto_files: &Vec<PathBuf>) -> Option<&DescriptorPool> {
+2 -8
View File
@@ -327,10 +327,7 @@ mod topology {
T: Eq + std::hash::Hash + Clone, T: Eq + std::hash::Hash + Clone,
{ {
pub fn new() -> Self { pub fn new() -> Self {
SimpleTopoSort { SimpleTopoSort { out_graph: HashMap::new(), in_graph: HashMap::new() }
out_graph: HashMap::new(),
in_graph: HashMap::new(),
}
} }
pub fn insert<I: IntoIterator<Item = T>>(&mut self, node: T, deps: I) { pub fn insert<I: IntoIterator<Item = T>>(&mut self, node: T, deps: I) {
@@ -376,10 +373,7 @@ mod topology {
} }
} }
SimpleTopoSortIter { SimpleTopoSortIter { data, zero_indegree }
data,
zero_indegree,
}
} }
} }
+3 -4
View File
@@ -1,11 +1,11 @@
use crate::error::Result; use crate::error::Result;
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder}; use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
use hyper_util::client::legacy::connect::HttpConnector;
use hyper_util::client::legacy::Client; use hyper_util::client::legacy::Client;
use hyper_util::client::legacy::connect::HttpConnector;
use hyper_util::rt::TokioExecutor; use hyper_util::rt::TokioExecutor;
use log::info; use log::info;
use tonic::body::BoxBody; use tonic::body::BoxBody;
use yaak_tls::{get_tls_config, ClientCertificateConfig}; use yaak_tls::{ClientCertificateConfig, get_tls_config};
// I think ALPN breaks this because we're specifying http2_only // I think ALPN breaks this because we're specifying http2_only
const WITH_ALPN: bool = false; const WITH_ALPN: bool = false;
@@ -14,8 +14,7 @@ pub(crate) fn get_transport(
validate_certificates: bool, validate_certificates: bool,
client_cert: Option<ClientCertificateConfig>, client_cert: Option<ClientCertificateConfig>,
) -> Result<Client<HttpsConnector<HttpConnector>, BoxBody>> { ) -> Result<Client<HttpsConnector<HttpConnector>, BoxBody>> {
let tls_config = let tls_config = get_tls_config(validate_certificates, WITH_ALPN, client_cert.clone())?;
get_tls_config(validate_certificates, WITH_ALPN, client_cert.clone())?;
let mut http = HttpConnector::new(); let mut http = HttpConnector::new();
http.enforce_http(false); http.enforce_http(false);
+1 -6
View File
@@ -72,12 +72,7 @@ impl HttpConnectionOptions {
HttpConnectionProxySetting::Disabled => { HttpConnectionProxySetting::Disabled => {
client = client.no_proxy(); client = client.no_proxy();
} }
HttpConnectionProxySetting::Enabled { HttpConnectionProxySetting::Enabled { http, https, auth, bypass } => {
http,
https,
auth,
bypass,
} => {
for p in build_enabled_proxy(http, https, auth, bypass) { for p in build_enabled_proxy(http, https, auth, bypass) {
client = client.proxy(p) client = client.proxy(p)
} }
+8 -24
View File
@@ -55,12 +55,8 @@ mod placeholder_tests {
#[test] #[test]
fn placeholder_middle() { fn placeholder_middle() {
let p = HttpUrlParameter { let p =
name: ":foo".into(), HttpUrlParameter { name: ":foo".into(), value: "xxx".into(), enabled: true, id: None };
value: "xxx".into(),
enabled: true,
id: None,
};
assert_eq!( assert_eq!(
replace_path_placeholder(&p, "https://example.com/:foo/bar"), replace_path_placeholder(&p, "https://example.com/:foo/bar"),
"https://example.com/xxx/bar", "https://example.com/xxx/bar",
@@ -69,12 +65,8 @@ mod placeholder_tests {
#[test] #[test]
fn placeholder_end() { fn placeholder_end() {
let p = HttpUrlParameter { let p =
name: ":foo".into(), HttpUrlParameter { name: ":foo".into(), value: "xxx".into(), enabled: true, id: None };
value: "xxx".into(),
enabled: true,
id: None,
};
assert_eq!( assert_eq!(
replace_path_placeholder(&p, "https://example.com/:foo"), replace_path_placeholder(&p, "https://example.com/:foo"),
"https://example.com/xxx", "https://example.com/xxx",
@@ -83,12 +75,8 @@ mod placeholder_tests {
#[test] #[test]
fn placeholder_query() { fn placeholder_query() {
let p = HttpUrlParameter { let p =
name: ":foo".into(), HttpUrlParameter { name: ":foo".into(), value: "xxx".into(), enabled: true, id: None };
value: "xxx".into(),
enabled: true,
id: None,
};
assert_eq!( assert_eq!(
replace_path_placeholder(&p, "https://example.com/:foo?:foo"), replace_path_placeholder(&p, "https://example.com/:foo?:foo"),
"https://example.com/xxx?:foo", "https://example.com/xxx?:foo",
@@ -125,12 +113,8 @@ mod placeholder_tests {
#[test] #[test]
fn placeholder_prefix() { fn placeholder_prefix() {
let p = HttpUrlParameter { let p =
name: ":foo".into(), HttpUrlParameter { name: ":foo".into(), value: "xxx".into(), enabled: true, id: None };
value: "xxx".into(),
enabled: true,
id: None,
};
assert_eq!( assert_eq!(
replace_path_placeholder(&p, "https://example.com/:foooo"), replace_path_placeholder(&p, "https://example.com/:foooo"),
"https://example.com/:foooo", "https://example.com/:foooo",
+1 -2
View File
@@ -1,7 +1,6 @@
use tauri::{ use tauri::{
generate_handler, Runtime, generate_handler,
plugin::{Builder, TauriPlugin}, plugin::{Builder, TauriPlugin},
Runtime,
}; };
mod commands; mod commands;
+4 -15
View File
@@ -114,10 +114,7 @@ pub async fn activate_license<R: Runtime>(
if response.status().is_client_error() { if response.status().is_client_error() {
let body: APIErrorResponsePayload = response.json().await?; let body: APIErrorResponsePayload = response.json().await?;
return Err(ClientError { return Err(ClientError { message: body.message, error: body.error });
message: body.message,
error: body.error,
});
} }
if response.status().is_server_error() { if response.status().is_server_error() {
@@ -154,10 +151,7 @@ pub async fn deactivate_license<R: Runtime>(window: &WebviewWindow<R>) -> Result
if response.status().is_client_error() { if response.status().is_client_error() {
let body: APIErrorResponsePayload = response.json().await?; let body: APIErrorResponsePayload = response.json().await?;
return Err(ClientError { return Err(ClientError { message: body.message, error: body.error });
message: body.message,
error: body.error,
});
} }
if response.status().is_server_error() { if response.status().is_server_error() {
@@ -192,9 +186,7 @@ pub async fn check_license<R: Runtime>(window: &WebviewWindow<R>) -> Result<Lice
match (has_activation_id, trial_period_active) { match (has_activation_id, trial_period_active) {
(false, true) => Ok(LicenseCheckStatus::Trialing { end: trial_end }), (false, true) => Ok(LicenseCheckStatus::Trialing { end: trial_end }),
(false, false) => Ok(LicenseCheckStatus::PersonalUse { (false, false) => Ok(LicenseCheckStatus::PersonalUse { trial_ended: trial_end }),
trial_ended: trial_end,
}),
(true, _) => { (true, _) => {
info!("Checking license activation"); info!("Checking license activation");
// A license has been activated, so let's check the license server // A license has been activated, so let's check the license server
@@ -204,10 +196,7 @@ pub async fn check_license<R: Runtime>(window: &WebviewWindow<R>) -> Result<Lice
if response.status().is_client_error() { if response.status().is_client_error() {
let body: APIErrorResponsePayload = response.json().await?; let body: APIErrorResponsePayload = response.json().await?;
return Err(ClientError { return Err(ClientError { message: body.message, error: body.error });
message: body.message,
error: body.error,
});
} }
if response.status().is_server_error() { if response.status().is_server_error() {
+1 -1
View File
@@ -1,4 +1,4 @@
use tauri::{command, Runtime, Window}; use tauri::{Runtime, Window, command};
#[command] #[command]
pub(crate) fn set_title<R: Runtime>(window: Window<R>, title: &str) { pub(crate) fn set_title<R: Runtime>(window: Window<R>, title: &str) {
+1 -3
View File
@@ -27,9 +27,7 @@ pub(crate) struct PluginState {
pub fn init<R: Runtime>() -> TauriPlugin<R> { pub fn init<R: Runtime>() -> TauriPlugin<R> {
let mut builder = plugin::Builder::new("yaak-mac-window") let mut builder = plugin::Builder::new("yaak-mac-window")
.setup(move |app, _| { .setup(move |app, _| {
app.manage(PluginState { app.manage(PluginState { native_titlebar: AtomicBool::new(false) });
native_titlebar: AtomicBool::new(false),
});
Ok(()) Ok(())
}) })
.invoke_handler(generate_handler![set_title, set_theme]); .invoke_handler(generate_handler![set_title, set_theme]);
+1 -3
View File
@@ -371,9 +371,7 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: &Window<R>) {
// Are we de-allocing this properly? (I miss safe Rust :( ) // Are we de-allocing this properly? (I miss safe Rust :( )
let window_label = window.label().to_string(); let window_label = window.label().to_string();
let app_state = WindowState { let app_state = WindowState { window: window.clone() };
window: window.clone(),
};
let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void; let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void;
let random_str: String = let random_str: String =
rand::rng().sample_iter(&Alphanumeric).take(20).map(char::from).collect(); rand::rng().sample_iter(&Alphanumeric).take(20).map(char::from).collect();
@@ -1,8 +1,6 @@
use crate::db_context::DbContext; use crate::db_context::DbContext;
use crate::error::Result; use crate::error::Result;
use crate::models::{ use crate::models::{GrpcRequest, HttpRequest, WebsocketRequest};
GrpcRequest, HttpRequest, WebsocketRequest,
};
pub enum AnyRequest { pub enum AnyRequest {
HttpRequest(HttpRequest), HttpRequest(HttpRequest),
@@ -143,11 +143,7 @@ impl<'a> DbContext<'a> {
} }
self.upsert( self.upsert(
&Environment { &Environment { name, variables: cleaned_variables, ..environment.clone() },
name,
variables: cleaned_variables,
..environment.clone()
},
source, source,
) )
} }
+9 -28
View File
@@ -1,7 +1,10 @@
use crate::connection_or_tx::ConnectionOrTx; use crate::connection_or_tx::ConnectionOrTx;
use crate::db_context::DbContext; use crate::db_context::DbContext;
use crate::error::Result; use crate::error::Result;
use crate::models::{Environment, EnvironmentIden, Folder, FolderIden, GrpcRequest, GrpcRequestIden, HttpRequest, HttpRequestHeader, HttpRequestIden, WebsocketRequest, WebsocketRequestIden}; use crate::models::{
Environment, EnvironmentIden, Folder, FolderIden, GrpcRequest, GrpcRequestIden, HttpRequest,
HttpRequestHeader, HttpRequestIden, WebsocketRequest, WebsocketRequestIden,
};
use crate::util::UpdateSource; use crate::util::UpdateSource;
use serde_json::Value; use serde_json::Value;
use std::collections::BTreeMap; use std::collections::BTreeMap;
@@ -69,57 +72,35 @@ impl<'a> DbContext<'a> {
for m in self.find_many::<HttpRequest>(HttpRequestIden::FolderId, fid, None)? { for m in self.find_many::<HttpRequest>(HttpRequestIden::FolderId, fid, None)? {
self.upsert_http_request( self.upsert_http_request(
&HttpRequest { &HttpRequest { id: "".into(), folder_id: Some(new_folder.id.clone()), ..m },
id: "".into(),
folder_id: Some(new_folder.id.clone()),
..m
},
source, source,
)?; )?;
} }
for m in self.find_many::<WebsocketRequest>(WebsocketRequestIden::FolderId, fid, None)? { for m in self.find_many::<WebsocketRequest>(WebsocketRequestIden::FolderId, fid, None)? {
self.upsert_websocket_request( self.upsert_websocket_request(
&WebsocketRequest { &WebsocketRequest { id: "".into(), folder_id: Some(new_folder.id.clone()), ..m },
id: "".into(),
folder_id: Some(new_folder.id.clone()),
..m
},
source, source,
)?; )?;
} }
for m in self.find_many::<GrpcRequest>(GrpcRequestIden::FolderId, fid, None)? { for m in self.find_many::<GrpcRequest>(GrpcRequestIden::FolderId, fid, None)? {
self.upsert_grpc_request( self.upsert_grpc_request(
&GrpcRequest { &GrpcRequest { id: "".into(), folder_id: Some(new_folder.id.clone()), ..m },
id: "".into(),
folder_id: Some(new_folder.id.clone()),
..m
},
source, source,
)?; )?;
} }
for m in self.find_many::<Environment>(EnvironmentIden::ParentId, fid, None)? { for m in self.find_many::<Environment>(EnvironmentIden::ParentId, fid, None)? {
self.upsert_environment( self.upsert_environment(
&Environment { &Environment { id: "".into(), parent_id: Some(new_folder.id.clone()), ..m },
id: "".into(),
parent_id: Some(new_folder.id.clone()),
..m
},
source, source,
)?; )?;
} }
for m in self.find_many::<Folder>(FolderIden::FolderId, fid, None)? { for m in self.find_many::<Folder>(FolderIden::FolderId, fid, None)? {
// Recurse down // Recurse down
self.duplicate_folder( self.duplicate_folder(&Folder { folder_id: Some(new_folder.id.clone()), ..m }, source)?;
&Folder {
folder_id: Some(new_folder.id.clone()),
..m
},
source,
)?;
} }
Ok(new_folder) Ok(new_folder)
@@ -31,13 +31,9 @@ impl<'a> DbContext<'a> {
}, },
source, source,
), ),
Some(introspection) => self.upsert( Some(introspection) => {
&GraphQlIntrospection { self.upsert(&GraphQlIntrospection { content, ..introspection }, source)
content, }
..introspection
},
source,
),
} }
} }
@@ -1,12 +1,12 @@
use crate::db_context::DbContext;
use crate::error::Result; use crate::error::Result;
use crate::models::{HttpResponse, HttpResponseIden, HttpResponseState}; use crate::models::{HttpResponse, HttpResponseIden, HttpResponseState};
use crate::queries::MAX_HISTORY_ITEMS;
use crate::util::UpdateSource; use crate::util::UpdateSource;
use log::{debug, error}; use log::{debug, error};
use sea_query::{Expr, Query, SqliteQueryBuilder}; use sea_query::{Expr, Query, SqliteQueryBuilder};
use sea_query_rusqlite::RusqliteBinder; use sea_query_rusqlite::RusqliteBinder;
use std::fs; use std::fs;
use crate::db_context::DbContext;
use crate::queries::MAX_HISTORY_ITEMS;
impl<'a> DbContext<'a> { impl<'a> DbContext<'a> {
pub fn get_http_response(&self, id: &str) -> Result<HttpResponse> { pub fn get_http_response(&self, id: &str) -> Result<HttpResponse> {
@@ -101,10 +101,6 @@ impl<'a> DbContext<'a> {
response: &HttpResponse, response: &HttpResponse,
source: &UpdateSource, source: &UpdateSource,
) -> Result<HttpResponse> { ) -> Result<HttpResponse> {
if response.id.is_empty() { if response.id.is_empty() { Ok(response.clone()) } else { self.upsert(response, source) }
Ok(response.clone())
} else {
self.upsert(response, source)
}
} }
} }
@@ -1,8 +1,8 @@
use chrono::NaiveDateTime;
use crate::db_context::DbContext; use crate::db_context::DbContext;
use crate::error::Result; use crate::error::Result;
use crate::models::{KeyValue, KeyValueIden, UpsertModelInfo}; use crate::models::{KeyValue, KeyValueIden, UpsertModelInfo};
use crate::util::UpdateSource; use crate::util::UpdateSource;
use chrono::NaiveDateTime;
use log::error; use log::error;
use sea_query::{Asterisk, Cond, Expr, Query, SqliteQueryBuilder}; use sea_query::{Asterisk, Cond, Expr, Query, SqliteQueryBuilder};
use sea_query_rusqlite::RusqliteBinder; use sea_query_rusqlite::RusqliteBinder;
@@ -39,7 +39,12 @@ impl<'a> DbContext<'a> {
} }
} }
pub fn get_key_value_dte(&self, namespace: &str, key: &str, default: NaiveDateTime) -> NaiveDateTime { pub fn get_key_value_dte(
&self,
namespace: &str,
key: &str,
default: NaiveDateTime,
) -> NaiveDateTime {
match self.get_key_value_raw(namespace, key) { match self.get_key_value_raw(namespace, key) {
None => default, None => default,
Some(v) => { Some(v) => {
@@ -139,14 +144,8 @@ impl<'a> DbContext<'a> {
true, true,
), ),
Some(kv) => ( Some(kv) => (
self.upsert_key_value( self.upsert_key_value(&KeyValue { value: value.to_string(), ..kv }, source)
&KeyValue { .expect("Failed to update key value"),
value: value.to_string(),
..kv
},
source,
)
.expect("Failed to update key value"),
false, false,
), ),
} }
@@ -1,10 +1,10 @@
use crate::db_context::DbContext;
use crate::error::Result; use crate::error::Result;
use crate::models::{SyncState, SyncStateIden, UpsertModelInfo}; use crate::models::{SyncState, SyncStateIden, UpsertModelInfo};
use crate::util::UpdateSource; use crate::util::UpdateSource;
use sea_query::{Asterisk, Cond, Expr, Query, SqliteQueryBuilder}; use sea_query::{Asterisk, Cond, Expr, Query, SqliteQueryBuilder};
use sea_query_rusqlite::RusqliteBinder; use sea_query_rusqlite::RusqliteBinder;
use std::path::Path; use std::path::Path;
use crate::db_context::DbContext;
impl<'a> DbContext<'a> { impl<'a> DbContext<'a> {
pub fn get_sync_state(&self, id: &str) -> Result<SyncState> { pub fn get_sync_state(&self, id: &str) -> Result<SyncState> {
@@ -1,9 +1,6 @@
use crate::db_context::DbContext; use crate::db_context::DbContext;
use crate::error::Result; use crate::error::Result;
use crate::models::{ use crate::models::{WebsocketEvent, WebsocketEventIden};
WebsocketEvent,
WebsocketEventIden,
};
use crate::util::UpdateSource; use crate::util::UpdateSource;
impl<'a> DbContext<'a> { impl<'a> DbContext<'a> {
@@ -56,7 +56,11 @@ impl<'a> DbContext<'a> {
websocket_request: &WebsocketRequest, websocket_request: &WebsocketRequest,
) -> Result<(Option<String>, BTreeMap<String, Value>, String)> { ) -> Result<(Option<String>, BTreeMap<String, Value>, String)> {
if let Some(at) = websocket_request.authentication_type.clone() { if let Some(at) = websocket_request.authentication_type.clone() {
return Ok((Some(at), websocket_request.authentication.clone(), websocket_request.id.clone())); return Ok((
Some(at),
websocket_request.authentication.clone(),
websocket_request.id.clone(),
));
} }
if let Some(folder_id) = websocket_request.folder_id.clone() { if let Some(folder_id) = websocket_request.folder_id.clone() {
@@ -14,10 +14,7 @@ impl<'a> DbContext<'a> {
self.find_many(WorkspaceMetaIden::WorkspaceId, workspace_id, None)?; self.find_many(WorkspaceMetaIden::WorkspaceId, workspace_id, None)?;
if workspace_metas.is_empty() { if workspace_metas.is_empty() {
let wm = WorkspaceMeta { let wm = WorkspaceMeta { workspace_id: workspace_id.to_string(), ..Default::default() };
workspace_id: workspace_id.to_string(),
..Default::default()
};
workspace_metas.push(self.upsert_workspace_meta(&wm, &UpdateSource::Background)?) workspace_metas.push(self.upsert_workspace_meta(&wm, &UpdateSource::Background)?)
} }
@@ -30,10 +27,8 @@ impl<'a> DbContext<'a> {
return Ok(workspace_meta); return Ok(workspace_meta);
} }
let workspace_meta = WorkspaceMeta { let workspace_meta =
workspace_id: workspace_id.to_string(), WorkspaceMeta { workspace_id: workspace_id.to_string(), ..Default::default() };
..Default::default()
};
info!("Creating WorkspaceMeta for {workspace_id}"); info!("Creating WorkspaceMeta for {workspace_id}");
+7 -17
View File
@@ -6,7 +6,7 @@ use crate::util::ModelPayload;
use r2d2::Pool; use r2d2::Pool;
use r2d2_sqlite::SqliteConnectionManager; use r2d2_sqlite::SqliteConnectionManager;
use rusqlite::TransactionBehavior; use rusqlite::TransactionBehavior;
use std::sync::{mpsc, Arc, Mutex}; use std::sync::{Arc, Mutex, mpsc};
use tauri::{Manager, Runtime, State}; use tauri::{Manager, Runtime, State};
pub trait QueryManagerExt<'a, R> { pub trait QueryManagerExt<'a, R> {
@@ -58,10 +58,7 @@ impl QueryManager {
pool: Pool<SqliteConnectionManager>, pool: Pool<SqliteConnectionManager>,
events_tx: mpsc::Sender<ModelPayload>, events_tx: mpsc::Sender<ModelPayload>,
) -> Self { ) -> Self {
QueryManager { QueryManager { pool: Arc::new(Mutex::new(pool)), events_tx }
pool: Arc::new(Mutex::new(pool)),
events_tx,
}
} }
pub fn connect(&self) -> DbContext<'_> { pub fn connect(&self) -> DbContext<'_> {
@@ -71,10 +68,7 @@ impl QueryManager {
.expect("Failed to gain lock on DB") .expect("Failed to gain lock on DB")
.get() .get()
.expect("Failed to get a new DB connection from the pool"); .expect("Failed to get a new DB connection from the pool");
DbContext { DbContext { events_tx: self.events_tx.clone(), conn: ConnectionOrTx::Connection(conn) }
events_tx: self.events_tx.clone(),
conn: ConnectionOrTx::Connection(conn),
}
} }
pub fn with_conn<F, T>(&self, func: F) -> T pub fn with_conn<F, T>(&self, func: F) -> T
@@ -88,10 +82,8 @@ impl QueryManager {
.get() .get()
.expect("Failed to get new DB connection from the pool"); .expect("Failed to get new DB connection from the pool");
let db_context = DbContext { let db_context =
events_tx: self.events_tx.clone(), DbContext { events_tx: self.events_tx.clone(), conn: ConnectionOrTx::Connection(conn) };
conn: ConnectionOrTx::Connection(conn),
};
func(&db_context) func(&db_context)
} }
@@ -113,10 +105,8 @@ impl QueryManager {
.transaction_with_behavior(TransactionBehavior::Immediate) .transaction_with_behavior(TransactionBehavior::Immediate)
.expect("Failed to start DB transaction"); .expect("Failed to start DB transaction");
let db_context = DbContext { let db_context =
events_tx: self.events_tx.clone(), DbContext { events_tx: self.events_tx.clone(), conn: ConnectionOrTx::Transaction(&tx) };
conn: ConnectionOrTx::Transaction(&tx),
};
match func(&db_context) { match func(&db_context) {
Ok(val) => { Ok(val) => {
+1 -3
View File
@@ -62,9 +62,7 @@ pub enum UpdateSource {
impl UpdateSource { impl UpdateSource {
pub fn from_window<R: Runtime>(window: &WebviewWindow<R>) -> Self { pub fn from_window<R: Runtime>(window: &WebviewWindow<R>) -> Self {
Self::Window { Self::Window { label: window.label().to_string() }
label: window.label().to_string(),
}
} }
} }
+2 -7
View File
@@ -58,10 +58,7 @@ pub async fn check_plugin_updates<R: Runtime>(
.list_plugins()? .list_plugins()?
.into_iter() .into_iter()
.filter_map(|p| match get_plugin_meta(&Path::new(&p.directory)) { .filter_map(|p| match get_plugin_meta(&Path::new(&p.directory)) {
Ok(m) => Some(PluginNameVersion { Ok(m) => Some(PluginNameVersion { name: m.name, version: m.version }),
name: m.name,
version: m.version,
}),
Err(e) => { Err(e) => {
warn!("Failed to get plugin metadata: {}", e); warn!("Failed to get plugin metadata: {}", e);
None None
@@ -70,9 +67,7 @@ pub async fn check_plugin_updates<R: Runtime>(
.collect(); .collect();
let url = build_url("/updates"); let url = build_url("/updates");
let body = serde_json::to_vec(&PluginUpdatesResponse { let body = serde_json::to_vec(&PluginUpdatesResponse { plugins: name_versions })?;
plugins: name_versions,
})?;
let resp = yaak_api_client(app_handle)?.post(url.clone()).body(body).send().await?; let resp = yaak_api_client(app_handle)?.post(url.clone()).body(body).send().await?;
if !resp.status().is_success() { if !resp.status().is_success() {
return Err(ApiErr(format!("{} response to {}", resp.status(), url.to_string()))); return Err(ApiErr(format!("{} response to {}", resp.status(), url.to_string())));
+2 -2
View File
@@ -1,9 +1,9 @@
use crate::api::{ use crate::api::{
check_plugin_updates, search_plugins, PluginSearchResponse, PluginUpdatesResponse, PluginSearchResponse, PluginUpdatesResponse, check_plugin_updates, search_plugins,
}; };
use crate::error::Result; use crate::error::Result;
use crate::install::{delete_and_uninstall, download_and_install}; use crate::install::{delete_and_uninstall, download_and_install};
use tauri::{command, AppHandle, Runtime, WebviewWindow}; use tauri::{AppHandle, Runtime, WebviewWindow, command};
use yaak_models::models::Plugin; use yaak_models::models::Plugin;
#[command] #[command]
+2 -8
View File
@@ -45,11 +45,7 @@ pub struct PluginContext {
impl PluginContext { impl PluginContext {
pub fn new_empty() -> Self { pub fn new_empty() -> Self {
Self { Self { id: "default".to_string(), label: None, workspace_id: None }
id: "default".to_string(),
label: None,
workspace_id: None,
}
} }
pub fn new<R: Runtime>(window: &WebviewWindow<R>) -> Self { pub fn new<R: Runtime>(window: &WebviewWindow<R>) -> Self {
Self { Self {
@@ -1049,9 +1045,7 @@ pub enum Content {
impl Default for Content { impl Default for Content {
fn default() -> Self { fn default() -> Self {
Self::Text { Self::Text { content: String::default() }
content: String::default(),
}
} }
} }
+6 -6
View File
@@ -1,24 +1,24 @@
use std::sync::atomic::{AtomicBool, Ordering};
use crate::commands::{install, search, uninstall, updates}; use crate::commands::{install, search, uninstall, updates};
use crate::manager::PluginManager; use crate::manager::PluginManager;
use log::info; use log::info;
use std::sync::atomic::{AtomicBool, Ordering};
use tauri::plugin::{Builder, TauriPlugin}; use tauri::plugin::{Builder, TauriPlugin};
use tauri::{generate_handler, Manager, RunEvent, Runtime, State}; use tauri::{Manager, RunEvent, Runtime, State, generate_handler};
pub mod api;
mod checksum;
mod commands; mod commands;
pub mod error; pub mod error;
pub mod events; pub mod events;
pub mod install;
pub mod manager; pub mod manager;
pub mod native_template_functions; pub mod native_template_functions;
mod nodejs; mod nodejs;
pub mod plugin_handle; pub mod plugin_handle;
pub mod plugin_meta;
mod server_ws; mod server_ws;
pub mod template_callback; pub mod template_callback;
mod util; mod util;
mod checksum;
pub mod api;
pub mod install;
pub mod plugin_meta;
static EXITING: AtomicBool = AtomicBool::new(false); static EXITING: AtomicBool = AtomicBool::new(false);
+19 -30
View File
@@ -185,12 +185,8 @@ impl PluginManager {
.collect(); .collect();
let plugins = app_handle.db().list_plugins().unwrap_or_default(); let plugins = app_handle.db().list_plugins().unwrap_or_default();
let installed_plugin_dirs: Vec<PluginCandidate> = plugins let installed_plugin_dirs: Vec<PluginCandidate> =
.iter() plugins.iter().map(|p| PluginCandidate { dir: p.directory.to_owned() }).collect();
.map(|p| PluginCandidate {
dir: p.directory.to_owned(),
})
.collect();
[bundled_plugin_dirs, installed_plugin_dirs].concat() [bundled_plugin_dirs, installed_plugin_dirs].concat()
} }
@@ -524,9 +520,7 @@ impl PluginManager {
RenderPurpose::Preview, RenderPurpose::Preview,
); );
// We don't want to fail for this op because the UI will not be able to list any auth types then // We don't want to fail for this op because the UI will not be able to list any auth types then
let render_opt = RenderOptions { let render_opt = RenderOptions { error_behavior: RenderErrorBehavior::ReturnEmpty };
error_behavior: RenderErrorBehavior::ReturnEmpty,
};
let rendered_values = render_json_value_raw(json!(values), vars, &cb, &render_opt).await?; let rendered_values = render_json_value_raw(json!(values), vars, &cb, &render_opt).await?;
let context_id = format!("{:x}", md5::compute(model_id.to_string())); let context_id = format!("{:x}", md5::compute(model_id.to_string()));
@@ -643,9 +637,7 @@ impl PluginManager {
RenderPurpose::Preview, RenderPurpose::Preview,
); );
// We don't want to fail for this op because the UI will not be able to list any auth types then // We don't want to fail for this op because the UI will not be able to list any auth types then
let render_opt = RenderOptions { let render_opt = RenderOptions { error_behavior: RenderErrorBehavior::ReturnEmpty };
error_behavior: RenderErrorBehavior::ReturnEmpty,
};
let rendered_values = render_json_value_raw(json!(values), vars, &cb, &render_opt).await?; let rendered_values = render_json_value_raw(json!(values), vars, &cb, &render_opt).await?;
let context_id = format!("{:x}", md5::compute(model_id.to_string())); let context_id = format!("{:x}", md5::compute(model_id.to_string()));
let event = self let event = self
@@ -688,9 +680,7 @@ impl PluginManager {
&PluginContext::new(&window), &PluginContext::new(&window),
RenderPurpose::Preview, RenderPurpose::Preview,
), ),
&RenderOptions { &RenderOptions { error_behavior: RenderErrorBehavior::Throw },
error_behavior: RenderErrorBehavior::Throw,
},
) )
.await?; .await?;
let results = self.get_http_authentication_summaries(window).await?; let results = self.get_http_authentication_summaries(window).await?;
@@ -807,21 +797,20 @@ impl PluginManager {
.await .await
.map_err(|e| RenderError(format!("Failed to call template function {e:}")))?; .map_err(|e| RenderError(format!("Failed to call template function {e:}")))?;
let value = events.into_iter().find_map(|e| match e.payload { let value =
// Error returned events.into_iter().find_map(|e| match e.payload {
InternalEventPayload::CallTemplateFunctionResponse(CallTemplateFunctionResponse { // Error returned
error: Some(error), InternalEventPayload::CallTemplateFunctionResponse(
.. CallTemplateFunctionResponse { error: Some(error), .. },
}) => Some(Err(error)), ) => Some(Err(error)),
// Value or null returned // Value or null returned
InternalEventPayload::CallTemplateFunctionResponse(CallTemplateFunctionResponse { InternalEventPayload::CallTemplateFunctionResponse(
value, CallTemplateFunctionResponse { value, .. },
.. ) => Some(Ok(value.unwrap_or_default())),
}) => Some(Ok(value.unwrap_or_default())), // Generic error returned
// Generic error returned InternalEventPayload::ErrorResponse(ErrorResponse { error }) => Some(Err(error)),
InternalEventPayload::ErrorResponse(ErrorResponse { error }) => Some(Err(error)), _ => None,
_ => None, });
});
match value { match value {
None => Err(RenderError(format!("Template function {fn_name}(…) not found "))), None => Err(RenderError(format!("Template function {fn_name}(…) not found "))),
@@ -4,17 +4,17 @@ use crate::events::{
TemplateFunctionPreviewType, TemplateFunctionPreviewType,
}; };
use crate::template_callback::PluginTemplateCallback; use crate::template_callback::PluginTemplateCallback;
use base64::prelude::BASE64_STANDARD;
use base64::Engine; use base64::Engine;
use base64::prelude::BASE64_STANDARD;
use keyring::Error::NoEntry; use keyring::Error::NoEntry;
use log::{debug, info}; use log::{debug, info};
use std::collections::HashMap; use std::collections::HashMap;
use tauri::{AppHandle, Runtime}; use tauri::{AppHandle, Runtime};
use yaak_common::platform::{get_os, OperatingSystem}; use yaak_common::platform::{OperatingSystem, get_os};
use yaak_crypto::manager::EncryptionManagerExt; use yaak_crypto::manager::EncryptionManagerExt;
use yaak_templates::error::Error::RenderError; use yaak_templates::error::Error::RenderError;
use yaak_templates::error::Result; use yaak_templates::error::Result;
use yaak_templates::{transform_args, FnArg, Parser, Token, Tokens, Val}; use yaak_templates::{FnArg, Parser, Token, Tokens, Val, transform_args};
pub(crate) fn template_function_secure() -> TemplateFunction { pub(crate) fn template_function_secure() -> TemplateFunction {
TemplateFunction { TemplateFunction {
@@ -179,9 +179,7 @@ pub fn decrypt_secure_template_function<R: Runtime>(
for token in parsed.tokens.iter() { for token in parsed.tokens.iter() {
match token { match token {
Token::Tag { Token::Tag { val: Val::Fn { name, args } } if name == "secure" => {
val: Val::Fn { name, args },
} if name == "secure" => {
let mut args_map = HashMap::new(); let mut args_map = HashMap::new();
for a in args { for a in args {
match a.clone().value { match a.clone().value {
@@ -228,7 +226,7 @@ pub fn encrypt_secure_template_function<R: Runtime>(
tokens, tokens,
&PluginTemplateCallback::new(app_handle, plugin_context, RenderPurpose::Preview), &PluginTemplateCallback::new(app_handle, plugin_context, RenderPurpose::Preview),
)? )?
.to_string()) .to_string())
} }
pub fn template_function_keychain_run(args: HashMap<String, serde_json::Value>) -> Result<String> { pub fn template_function_keychain_run(args: HashMap<String, serde_json::Value>) -> Result<String> {
+1 -1
View File
@@ -3,8 +3,8 @@ use log::{info, warn};
use std::net::SocketAddr; use std::net::SocketAddr;
use tauri::path::BaseDirectory; use tauri::path::BaseDirectory;
use tauri::{AppHandle, Manager, Runtime}; use tauri::{AppHandle, Manager, Runtime};
use tauri_plugin_shell::process::CommandEvent;
use tauri_plugin_shell::ShellExt; use tauri_plugin_shell::ShellExt;
use tauri_plugin_shell::process::CommandEvent;
use tokio::sync::watch::Receiver; use tokio::sync::watch::Receiver;
pub async fn start_nodejs_plugin_runtime<R: Runtime>( pub async fn start_nodejs_plugin_runtime<R: Runtime>(
+2 -2
View File
@@ -3,10 +3,10 @@ use futures_util::{SinkExt, StreamExt};
use log::{error, info, warn}; use log::{error, info, warn};
use std::sync::Arc; use std::sync::Arc;
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
use tokio::sync::{mpsc, Mutex}; use tokio::sync::{Mutex, mpsc};
use tokio_tungstenite::accept_async_with_config; use tokio_tungstenite::accept_async_with_config;
use tokio_tungstenite::tungstenite::protocol::WebSocketConfig;
use tokio_tungstenite::tungstenite::Message; use tokio_tungstenite::tungstenite::Message;
use tokio_tungstenite::tungstenite::protocol::WebSocketConfig;
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct PluginRuntimeServerWebsocket { pub(crate) struct PluginRuntimeServerWebsocket {
+1 -1
View File
@@ -1,5 +1,5 @@
use rand::distr::Alphanumeric;
use rand::Rng; use rand::Rng;
use rand::distr::Alphanumeric;
pub fn gen_id() -> String { pub fn gen_id() -> String {
rand::rng().sample_iter(&Alphanumeric).take(5).map(char::from).collect() rand::rng().sample_iter(&Alphanumeric).take(5).map(char::from).collect()
+6 -6
View File
@@ -1,18 +1,18 @@
use crate::error::Error::InvalidSyncDirectory;
use crate::error::Result; use crate::error::Result;
use crate::sync::{ use crate::sync::{
apply_sync_ops, apply_sync_state_ops, compute_sync_ops, get_db_candidates, get_fs_candidates, FsCandidate, FsCandidate, SyncOp, apply_sync_ops, apply_sync_state_ops, compute_sync_ops, get_db_candidates,
SyncOp, get_fs_candidates,
}; };
use crate::watch::{watch_directory, WatchEvent}; use crate::watch::{WatchEvent, watch_directory};
use chrono::Utc; use chrono::Utc;
use log::warn; use log::warn;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::Path; use std::path::Path;
use tauri::ipc::Channel; use tauri::ipc::Channel;
use tauri::{command, AppHandle, Listener, Runtime}; use tauri::{AppHandle, Listener, Runtime, command};
use tokio::sync::watch; use tokio::sync::watch;
use ts_rs::TS; use ts_rs::TS;
use crate::error::Error::InvalidSyncDirectory;
#[command] #[command]
pub async fn calculate<R: Runtime>( pub async fn calculate<R: Runtime>(
@@ -21,7 +21,7 @@ pub async fn calculate<R: Runtime>(
sync_dir: &Path, sync_dir: &Path,
) -> Result<Vec<SyncOp>> { ) -> Result<Vec<SyncOp>> {
if !sync_dir.exists() { if !sync_dir.exists() {
return Err(InvalidSyncDirectory(sync_dir.to_string_lossy().to_string())) return Err(InvalidSyncDirectory(sync_dir.to_string_lossy().to_string()));
} }
let db_candidates = get_db_candidates(&app_handle, workspace_id, sync_dir)?; let db_candidates = get_db_candidates(&app_handle, workspace_id, sync_dir)?;
+1 -2
View File
@@ -1,8 +1,7 @@
use crate::commands::{apply, calculate, calculate_fs, watch}; use crate::commands::{apply, calculate, calculate_fs, watch};
use tauri::{ use tauri::{
generate_handler, Runtime, generate_handler,
plugin::{Builder, TauriPlugin}, plugin::{Builder, TauriPlugin},
Runtime,
}; };
mod commands; mod commands;
+23 -59
View File
@@ -202,11 +202,7 @@ pub(crate) fn get_fs_candidates(dir: &Path) -> Result<Vec<FsCandidate>> {
}; };
let rel_path = Path::new(&dir_entry.file_name()).to_path_buf(); let rel_path = Path::new(&dir_entry.file_name()).to_path_buf();
candidates.push(FsCandidate { candidates.push(FsCandidate { rel_path, model, checksum })
rel_path,
model,
checksum,
})
} }
Ok(candidates) Ok(candidates)
@@ -236,28 +232,25 @@ pub(crate) fn compute_sync_ops(
(None, Some(fs)) => SyncOp::DbCreate { fs: fs.to_owned() }, (None, Some(fs)) => SyncOp::DbCreate { fs: fs.to_owned() },
// DB unchanged <-> FS missing // DB unchanged <-> FS missing
(Some(DbCandidate::Unmodified(model, sync_state)), None) => SyncOp::DbDelete { (Some(DbCandidate::Unmodified(model, sync_state)), None) => {
model: model.to_owned(), SyncOp::DbDelete { model: model.to_owned(), state: sync_state.to_owned() }
state: sync_state.to_owned(), }
},
// DB modified <-> FS missing // DB modified <-> FS missing
(Some(DbCandidate::Modified(model, sync_state)), None) => SyncOp::FsUpdate { (Some(DbCandidate::Modified(model, sync_state)), None) => {
model: model.to_owned(), SyncOp::FsUpdate { model: model.to_owned(), state: sync_state.to_owned() }
state: sync_state.to_owned(), }
},
// DB added <-> FS missing // DB added <-> FS missing
(Some(DbCandidate::Added(model)), None) => SyncOp::FsCreate { (Some(DbCandidate::Added(model)), None) => {
model: model.to_owned(), SyncOp::FsCreate { model: model.to_owned() }
}, }
// DB deleted <-> FS missing // DB deleted <-> FS missing
// Already deleted on FS, but sending it so the SyncState gets dealt with // Already deleted on FS, but sending it so the SyncState gets dealt with
(Some(DbCandidate::Deleted(sync_state)), None) => SyncOp::FsDelete { (Some(DbCandidate::Deleted(sync_state)), None) => {
state: sync_state.to_owned(), SyncOp::FsDelete { state: sync_state.to_owned(), fs: None }
fs: None, }
},
// DB unchanged <-> FS exists // DB unchanged <-> FS exists
(Some(DbCandidate::Unmodified(_, sync_state)), Some(fs_candidate)) => { (Some(DbCandidate::Unmodified(_, sync_state)), Some(fs_candidate)) => {
@@ -274,10 +267,7 @@ pub(crate) fn compute_sync_ops(
// DB modified <-> FS exists // DB modified <-> FS exists
(Some(DbCandidate::Modified(model, sync_state)), Some(fs_candidate)) => { (Some(DbCandidate::Modified(model, sync_state)), Some(fs_candidate)) => {
if sync_state.checksum == fs_candidate.checksum { if sync_state.checksum == fs_candidate.checksum {
SyncOp::FsUpdate { SyncOp::FsUpdate { model: model.to_owned(), state: sync_state.to_owned() }
model: model.to_owned(),
state: sync_state.to_owned(),
}
} else if model.updated_at() < fs_candidate.model.updated_at() { } else if model.updated_at() < fs_candidate.model.updated_at() {
// CONFLICT! Write to DB if the fs model is newer // CONFLICT! Write to DB if the fs model is newer
SyncOp::DbUpdate { SyncOp::DbUpdate {
@@ -286,19 +276,14 @@ pub(crate) fn compute_sync_ops(
} }
} else { } else {
// CONFLICT! Write to FS if the db model is newer // CONFLICT! Write to FS if the db model is newer
SyncOp::FsUpdate { SyncOp::FsUpdate { model: model.to_owned(), state: sync_state.to_owned() }
model: model.to_owned(),
state: sync_state.to_owned(),
}
} }
} }
// DB added <-> FS anything // DB added <-> FS anything
(Some(DbCandidate::Added(model)), Some(_)) => { (Some(DbCandidate::Added(model)), Some(_)) => {
// This would be super rare (impossible?), so let's follow the user's intention // This would be super rare (impossible?), so let's follow the user's intention
SyncOp::FsCreate { SyncOp::FsCreate { model: model.to_owned() }
model: model.to_owned(),
}
} }
// DB deleted <-> FS exists // DB deleted <-> FS exists
@@ -389,11 +374,7 @@ pub(crate) fn apply_sync_ops<R: Runtime>(
let (content, checksum) = model.to_file_contents(&rel_path)?; let (content, checksum) = model.to_file_contents(&rel_path)?;
let mut f = File::create(&abs_path)?; let mut f = File::create(&abs_path)?;
f.write_all(&content)?; f.write_all(&content)?;
SyncStateOp::Create { SyncStateOp::Create { model_id: model.id(), checksum, rel_path }
model_id: model.id(),
checksum,
rel_path,
}
} }
SyncOp::FsUpdate { model, state } => { SyncOp::FsUpdate { model, state } => {
// Always write the existing path // Always write the existing path
@@ -408,21 +389,14 @@ pub(crate) fn apply_sync_ops<R: Runtime>(
rel_path: rel_path.to_owned(), rel_path: rel_path.to_owned(),
} }
} }
SyncOp::FsDelete { SyncOp::FsDelete { state, fs: fs_candidate } => match fs_candidate {
state, None => SyncStateOp::Delete { state: state.to_owned() },
fs: fs_candidate,
} => match fs_candidate {
None => SyncStateOp::Delete {
state: state.to_owned(),
},
Some(_) => { Some(_) => {
// Always delete the existing path // Always delete the existing path
let rel_path = Path::new(&state.rel_path); let rel_path = Path::new(&state.rel_path);
let abs_path = Path::new(&state.sync_dir).join(&rel_path); let abs_path = Path::new(&state.sync_dir).join(&rel_path);
fs::remove_file(&abs_path)?; fs::remove_file(&abs_path)?;
SyncStateOp::Delete { SyncStateOp::Delete { state: state.to_owned() }
state: state.to_owned(),
}
} }
}, },
SyncOp::DbCreate { fs } => { SyncOp::DbCreate { fs } => {
@@ -463,9 +437,7 @@ pub(crate) fn apply_sync_ops<R: Runtime>(
} }
SyncOp::DbDelete { model, state } => { SyncOp::DbDelete { model, state } => {
delete_model(app_handle, &model)?; delete_model(app_handle, &model)?;
SyncStateOp::Delete { SyncStateOp::Delete { state: state.to_owned() }
state: state.to_owned(),
}
} }
SyncOp::IgnorePrivate { .. } => SyncStateOp::NoOp, SyncOp::IgnorePrivate { .. } => SyncStateOp::NoOp,
}); });
@@ -541,11 +513,7 @@ pub(crate) fn apply_sync_state_ops<R: Runtime>(
) -> Result<()> { ) -> Result<()> {
for op in ops { for op in ops {
match op { match op {
SyncStateOp::Create { SyncStateOp::Create { checksum, rel_path, model_id } => {
checksum,
rel_path,
model_id,
} => {
let sync_state = SyncState { let sync_state = SyncState {
workspace_id: workspace_id.to_string(), workspace_id: workspace_id.to_string(),
model_id, model_id,
@@ -557,11 +525,7 @@ pub(crate) fn apply_sync_state_ops<R: Runtime>(
}; };
app_handle.db().upsert_sync_state(&sync_state)?; app_handle.db().upsert_sync_state(&sync_state)?;
} }
SyncStateOp::Update { SyncStateOp::Update { state: sync_state, checksum, rel_path } => {
state: sync_state,
checksum,
rel_path,
} => {
let sync_state = SyncState { let sync_state = SyncState {
checksum, checksum,
sync_dir: sync_dir.to_str().unwrap().to_string(), sync_dir: sync_dir.to_str().unwrap().to_string(),
+42 -171
View File
@@ -97,10 +97,7 @@ impl Display for Token {
fn transform_val<T: TemplateCallback>(val: &Val, cb: &T) -> Result<Val> { fn transform_val<T: TemplateCallback>(val: &Val, cb: &T) -> Result<Val> {
let val = match val { let val = match val {
Val::Fn { Val::Fn { name: fn_name, args } => {
name: fn_name,
args,
} => {
let mut new_args: Vec<FnArg> = Vec::new(); let mut new_args: Vec<FnArg> = Vec::new();
for arg in args { for arg in args {
let value = match arg.clone().value { let value = match arg.clone().value {
@@ -112,15 +109,9 @@ fn transform_val<T: TemplateCallback>(val: &Val, cb: &T) -> Result<Val> {
}; };
let arg_name = arg.name.clone(); let arg_name = arg.name.clone();
new_args.push(FnArg { new_args.push(FnArg { name: arg_name, value });
name: arg_name,
value,
});
}
Val::Fn {
name: fn_name.clone(),
args: new_args,
} }
Val::Fn { name: fn_name.clone(), args: new_args }
} }
_ => val.clone(), _ => val.clone(),
}; };
@@ -160,10 +151,7 @@ pub struct Parser {
impl Parser { impl Parser {
pub fn new(text: &str) -> Parser { pub fn new(text: &str) -> Parser {
Parser { Parser { chars: text.chars().collect(), ..Parser::default() }
chars: text.chars().collect(),
..Parser::default()
}
} }
pub fn parse(&mut self) -> Result<Tokens> { pub fn parse(&mut self) -> Result<Tokens> {
@@ -195,9 +183,7 @@ impl Parser {
} }
self.push_token(Token::Eof); self.push_token(Token::Eof);
Ok(Tokens { Ok(Tokens { tokens: self.tokens.clone() })
tokens: self.tokens.clone(),
})
} }
fn parse_tag(&mut self) -> Result<Option<Token>> { fn parse_tag(&mut self) -> Result<Option<Token>> {
@@ -463,9 +449,7 @@ impl Parser {
fn push_token(&mut self, token: Token) { fn push_token(&mut self, token: Token) {
// Push any text we've accumulated // Push any text we've accumulated
if !self.curr_text.is_empty() { if !self.curr_text.is_empty() {
let text_token = Token::Raw { let text_token = Token::Raw { text: self.curr_text.clone() };
text: self.curr_text.clone(),
};
self.tokens.push(text_token); self.tokens.push(text_token);
self.curr_text.clear(); self.curr_text.clear();
} }
@@ -501,12 +485,7 @@ mod tests {
let mut p = Parser::new(r#"\${[ foo ]}"#); let mut p = Parser::new(r#"\${[ foo ]}"#);
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![Token::Raw { text: "${[ foo ]}".to_string() }, Token::Eof]
Token::Raw {
text: "${[ foo ]}".to_string()
},
Token::Eof
]
); );
Ok(()) Ok(())
} }
@@ -517,12 +496,8 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Raw { Token::Raw { text: r#"\\"#.to_string() },
text: r#"\\"#.to_string() Token::Tag { val: Val::Var { name: "foo".into() } },
},
Token::Tag {
val: Val::Var { name: "foo".into() }
},
Token::Eof Token::Eof
] ]
); );
@@ -535,9 +510,7 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Tag { Token::Tag { val: Val::Var { name: "foo".into() } },
val: Val::Var { name: "foo".into() }
},
Token::Eof Token::Eof
] ]
); );
@@ -550,9 +523,7 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Tag { Token::Tag { val: Val::Var { name: "a-b".into() } },
val: Val::Var { name: "a-b".into() }
},
Token::Eof Token::Eof
] ]
); );
@@ -566,9 +537,7 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Tag { Token::Tag { val: Val::Var { name: "a_b".into() } },
val: Val::Var { name: "a_b".into() }
},
Token::Eof Token::Eof
] ]
); );
@@ -599,9 +568,7 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Tag { Token::Tag { val: Val::Var { name: "_a".into() } },
val: Val::Var { name: "_a".into() }
},
Token::Eof Token::Eof
] ]
); );
@@ -615,12 +582,8 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Tag { Token::Tag { val: Val::Bool { value: true } },
val: Val::Bool { value: true }, Token::Tag { val: Val::Bool { value: false } },
},
Token::Tag {
val: Val::Bool { value: false },
},
Token::Eof Token::Eof
] ]
); );
@@ -633,12 +596,7 @@ mod tests {
let mut p = Parser::new("${[ foo bar ]}"); let mut p = Parser::new("${[ foo bar ]}");
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![Token::Raw { text: "${[ foo bar ]}".into() }, Token::Eof]
Token::Raw {
text: "${[ foo bar ]}".into()
},
Token::Eof
]
); );
Ok(()) Ok(())
@@ -650,11 +608,7 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Tag { Token::Tag { val: Val::Str { text: r#"foo 'bar' baz"#.into() } },
val: Val::Str {
text: r#"foo 'bar' baz"#.into()
}
},
Token::Eof Token::Eof
] ]
); );
@@ -668,11 +622,7 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Tag { Token::Tag { val: Val::Str { text: r#"foo 'bar' baz"#.into() } },
val: Val::Str {
text: r#"foo 'bar' baz"#.into()
}
},
Token::Eof Token::Eof
] ]
); );
@@ -686,15 +636,9 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Raw { Token::Raw { text: "Hello ".to_string() },
text: "Hello ".to_string() Token::Tag { val: Val::Var { name: "foo".into() } },
}, Token::Raw { text: "!".to_string() },
Token::Tag {
val: Val::Var { name: "foo".into() }
},
Token::Raw {
text: "!".to_string()
},
Token::Eof, Token::Eof,
] ]
); );
@@ -708,12 +652,7 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Tag { Token::Tag { val: Val::Fn { name: "foo".into(), args: Vec::new() } },
val: Val::Fn {
name: "foo".into(),
args: Vec::new(),
}
},
Token::Eof Token::Eof
] ]
); );
@@ -727,12 +666,7 @@ mod tests {
assert_eq!( assert_eq!(
p.parse()?.tokens, p.parse()?.tokens,
vec![ vec![
Token::Tag { Token::Tag { val: Val::Fn { name: "foo.bar.baz".into(), args: Vec::new() } },
val: Val::Fn {
name: "foo.bar.baz".into(),
args: Vec::new(),
}
},
Token::Eof Token::Eof
] ]
); );
@@ -772,18 +706,9 @@ mod tests {
val: Val::Fn { val: Val::Fn {
name: "foo".into(), name: "foo".into(),
args: vec![ args: vec![
FnArg { FnArg { name: "a".into(), value: Val::Var { name: "bar".into() } },
name: "a".into(), FnArg { name: "b".into(), value: Val::Var { name: "baz".into() } },
value: Val::Var { name: "bar".into() } FnArg { name: "c".into(), value: Val::Var { name: "qux".into() } },
},
FnArg {
name: "b".into(),
value: Val::Var { name: "baz".into() }
},
FnArg {
name: "c".into(),
value: Val::Var { name: "qux".into() }
},
], ],
} }
}, },
@@ -804,24 +729,13 @@ mod tests {
val: Val::Fn { val: Val::Fn {
name: "foo".into(), name: "foo".into(),
args: vec![ args: vec![
FnArg { FnArg { name: "aaa".into(), value: Val::Var { name: "bar".into() } },
name: "aaa".into(),
value: Val::Var { name: "bar".into() }
},
FnArg { FnArg {
name: "bb".into(), name: "bb".into(),
value: Val::Str { value: Val::Str { text: r#"baz 'hi'"#.into() }
text: r#"baz 'hi'"#.into()
}
},
FnArg {
name: "c".into(),
value: Val::Var { name: "qux".into() }
},
FnArg {
name: "z".into(),
value: Val::Bool { value: true }
}, },
FnArg { name: "c".into(), value: Val::Var { name: "qux".into() } },
FnArg { name: "z".into(), value: Val::Bool { value: true } },
], ],
} }
}, },
@@ -843,10 +757,7 @@ mod tests {
name: "foo".into(), name: "foo".into(),
args: vec![FnArg { args: vec![FnArg {
name: "b".into(), name: "b".into(),
value: Val::Fn { value: Val::Fn { name: "bar".into(), args: vec![] }
name: "bar".into(),
args: vec![],
}
}], }],
} }
}, },
@@ -883,10 +794,7 @@ mod tests {
], ],
} }
}, },
FnArg { FnArg { name: "c".into(), value: Val::Str { text: "o".into() } },
name: "c".into(),
value: Val::Str { text: "o".into() }
},
], ],
} }
}, },
@@ -899,26 +807,14 @@ mod tests {
#[test] #[test]
fn token_display_var() -> Result<()> { fn token_display_var() -> Result<()> {
assert_eq!( assert_eq!(Val::Var { name: "foo".to_string() }.to_string(), "foo");
Val::Var {
name: "foo".to_string()
}
.to_string(),
"foo"
);
Ok(()) Ok(())
} }
#[test] #[test]
fn token_display_str() -> Result<()> { fn token_display_str() -> Result<()> {
assert_eq!( assert_eq!(Val::Str { text: "Hello You".to_string() }.to_string(), "'Hello You'");
Val::Str {
text: "Hello You".to_string()
}
.to_string(),
"'Hello You'"
);
Ok(()) Ok(())
} }
@@ -926,10 +822,7 @@ mod tests {
#[test] #[test]
fn token_display_complex_str() -> Result<()> { fn token_display_complex_str() -> Result<()> {
assert_eq!( assert_eq!(
Val::Str { Val::Str { text: "Hello 'You'".to_string() }.to_string(),
text: "Hello 'You'".to_string()
}
.to_string(),
"b64'SGVsbG8gJ1lvdSc'" "b64'SGVsbG8gJ1lvdSc'"
); );
@@ -942,16 +835,8 @@ mod tests {
Val::Fn { Val::Fn {
name: "fn".to_string(), name: "fn".to_string(),
args: vec![ args: vec![
FnArg { FnArg { name: "n".to_string(), value: Null },
name: "n".to_string(), FnArg { name: "a".to_string(), value: Val::Str { text: "aaa".to_string() } }
value: Null,
},
FnArg {
name: "a".to_string(),
value: Val::Str {
text: "aaa".to_string()
}
}
] ]
} }
.to_string(), .to_string(),
@@ -970,15 +855,11 @@ mod tests {
args: vec![ args: vec![
FnArg { FnArg {
name: "arg".to_string(), name: "arg".to_string(),
value: Val::Str { value: Val::Str { text: "v 'x'".to_string() }
text: "v 'x'".to_string()
}
}, },
FnArg { FnArg {
name: "arg2".to_string(), name: "arg2".to_string(),
value: Val::Var { value: Val::Var { name: "my_var".to_string() }
name: "my_var".to_string()
}
} }
] ]
} }
@@ -995,19 +876,9 @@ mod tests {
assert_eq!( assert_eq!(
Tokens { Tokens {
tokens: vec![ tokens: vec![
Token::Tag { Token::Tag { val: Val::Var { name: "my_var".to_string() } },
val: Val::Var { Token::Raw { text: " Some cool text ".to_string() },
name: "my_var".to_string() Token::Tag { val: Val::Str { text: "Hello World".to_string() } }
}
},
Token::Raw {
text: " Some cool text ".to_string(),
},
Token::Tag {
val: Val::Str {
text: "Hello World".to_string()
}
}
] ]
} }
.to_string(), .to_string(),
+21 -64
View File
@@ -194,9 +194,7 @@ mod parse_and_render_tests {
let template = ""; let template = "";
let vars = HashMap::new(); let vars = HashMap::new();
let result = ""; let result = "";
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string()); assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string());
Ok(()) Ok(())
} }
@@ -207,9 +205,7 @@ mod parse_and_render_tests {
let template = "Hello World!"; let template = "Hello World!";
let vars = HashMap::new(); let vars = HashMap::new();
let result = "Hello World!"; let result = "Hello World!";
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string()); assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string());
Ok(()) Ok(())
} }
@@ -220,9 +216,7 @@ mod parse_and_render_tests {
let template = "${[ foo ]}"; let template = "${[ foo ]}";
let vars = HashMap::from([("foo".to_string(), "bar".to_string())]); let vars = HashMap::from([("foo".to_string(), "bar".to_string())]);
let result = "bar"; let result = "bar";
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string()); assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string());
Ok(()) Ok(())
} }
@@ -237,9 +231,7 @@ mod parse_and_render_tests {
vars.insert("baz".to_string(), "baz".to_string()); vars.insert("baz".to_string(), "baz".to_string());
let result = "foo: bar: baz"; let result = "foo: bar: baz";
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string()); assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string());
Ok(()) Ok(())
} }
@@ -249,9 +241,7 @@ mod parse_and_render_tests {
let empty_cb = EmptyCB {}; let empty_cb = EmptyCB {};
let template = "${[ foo ]}"; let template = "${[ foo ]}";
let vars = HashMap::new(); let vars = HashMap::new();
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
assert_eq!( assert_eq!(
parse_and_render(template, &vars, &empty_cb, &opt).await, parse_and_render(template, &vars, &empty_cb, &opt).await,
Err(VariableNotFound("foo".to_string())) Err(VariableNotFound("foo".to_string()))
@@ -265,13 +255,8 @@ mod parse_and_render_tests {
let template = "${[ foo ]}"; let template = "${[ foo ]}";
let mut vars = HashMap::new(); let mut vars = HashMap::new();
vars.insert("foo".to_string(), "".to_string()); vars.insert("foo".to_string(), "".to_string());
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw, assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await, Ok("".to_string()));
};
assert_eq!(
parse_and_render(template, &vars, &empty_cb, &opt).await,
Ok("".to_string())
);
Ok(()) Ok(())
} }
@@ -281,9 +266,7 @@ mod parse_and_render_tests {
let template = "${[ foo ]}"; let template = "${[ foo ]}";
let mut vars = HashMap::new(); let mut vars = HashMap::new();
vars.insert("foo".to_string(), "${[ foo ]}".to_string()); vars.insert("foo".to_string(), "${[ foo ]}".to_string());
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
assert_eq!( assert_eq!(
parse_and_render(template, &vars, &empty_cb, &opt).await, parse_and_render(template, &vars, &empty_cb, &opt).await,
Err(RenderStackExceededError) Err(RenderStackExceededError)
@@ -297,9 +280,7 @@ mod parse_and_render_tests {
let template = "hello ${[ word ]} world!"; let template = "hello ${[ word ]} world!";
let vars = HashMap::from([("word".to_string(), "cruel".to_string())]); let vars = HashMap::from([("word".to_string(), "cruel".to_string())]);
let result = "hello cruel world!"; let result = "hello cruel world!";
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string()); assert_eq!(parse_and_render(template, &vars, &empty_cb, &opt).await?, result.to_string());
Ok(()) Ok(())
} }
@@ -309,9 +290,7 @@ mod parse_and_render_tests {
let vars = HashMap::new(); let vars = HashMap::new();
let template = r#"${[ say_hello(a='John', b='Kate') ]}"#; let template = r#"${[ say_hello(a='John', b='Kate') ]}"#;
let result = r#"say_hello: 2, Some(String("John")) Some(String("Kate"))"#; let result = r#"say_hello: 2, Some(String("John")) Some(String("Kate"))"#;
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
struct CB {} struct CB {}
impl TemplateCallback for CB { impl TemplateCallback for CB {
@@ -341,9 +320,7 @@ mod parse_and_render_tests {
let vars = HashMap::new(); let vars = HashMap::new();
let template = r#"${[ upper(foo='bar') ]}"#; let template = r#"${[ upper(foo='bar') ]}"#;
let result = r#""BAR""#; let result = r#""BAR""#;
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
struct CB {} struct CB {}
impl TemplateCallback for CB { impl TemplateCallback for CB {
async fn run( async fn run(
@@ -378,9 +355,7 @@ mod parse_and_render_tests {
vars.insert("foo".to_string(), "bar".to_string()); vars.insert("foo".to_string(), "bar".to_string());
let template = r#"${[ upper(foo=b64'Zm9vICdiYXInIGJheg') ]}"#; let template = r#"${[ upper(foo=b64'Zm9vICdiYXInIGJheg') ]}"#;
let result = r#""FOO 'BAR' BAZ""#; let result = r#""FOO 'BAR' BAZ""#;
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
struct CB {} struct CB {}
impl TemplateCallback for CB { impl TemplateCallback for CB {
async fn run( async fn run(
@@ -414,9 +389,7 @@ mod parse_and_render_tests {
vars.insert("foo".to_string(), "bar".to_string()); vars.insert("foo".to_string(), "bar".to_string());
let template = r#"${[ upper(foo='${[ foo ]}') ]}"#; let template = r#"${[ upper(foo='${[ foo ]}') ]}"#;
let result = r#""BAR""#; let result = r#""BAR""#;
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
struct CB {} struct CB {}
impl TemplateCallback for CB { impl TemplateCallback for CB {
@@ -452,9 +425,7 @@ mod parse_and_render_tests {
vars.insert("foo".to_string(), "bar".to_string()); vars.insert("foo".to_string(), "bar".to_string());
let template = r#"${[ no_op(inner='${[ foo ]}') ]}"#; let template = r#"${[ no_op(inner='${[ foo ]}') ]}"#;
let result = r#""bar""#; let result = r#""bar""#;
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
struct CB {} struct CB {}
impl TemplateCallback for CB { impl TemplateCallback for CB {
@@ -489,9 +460,7 @@ mod parse_and_render_tests {
let template = r#"${[ upper(foo=secret()) ]}"#; let template = r#"${[ upper(foo=secret()) ]}"#;
let result = r#""ABC""#; let result = r#""ABC""#;
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
struct CB {} struct CB {}
impl TemplateCallback for CB { impl TemplateCallback for CB {
async fn run( async fn run(
@@ -523,9 +492,7 @@ mod parse_and_render_tests {
async fn render_fn_err() -> Result<()> { async fn render_fn_err() -> Result<()> {
let vars = HashMap::new(); let vars = HashMap::new();
let template = r#"hello ${[ error() ]}"#; let template = r#"hello ${[ error() ]}"#;
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
struct CB {} struct CB {}
impl TemplateCallback for CB { impl TemplateCallback for CB {
@@ -591,9 +558,7 @@ mod render_json_value_raw_tests {
let v = json!("${[a]}"); let v = json!("${[a]}");
let mut vars = HashMap::new(); let mut vars = HashMap::new();
vars.insert("a".to_string(), "aaa".to_string()); vars.insert("a".to_string(), "aaa".to_string());
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
assert_eq!(render_json_value_raw(v, &vars, &EmptyCB {}, &opt).await?, json!("aaa")); assert_eq!(render_json_value_raw(v, &vars, &EmptyCB {}, &opt).await?, json!("aaa"));
Ok(()) Ok(())
@@ -604,9 +569,7 @@ mod render_json_value_raw_tests {
let v = json!(["${[a]}", "${[a]}"]); let v = json!(["${[a]}", "${[a]}"]);
let mut vars = HashMap::new(); let mut vars = HashMap::new();
vars.insert("a".to_string(), "aaa".to_string()); vars.insert("a".to_string(), "aaa".to_string());
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
let result = render_json_value_raw(v, &vars, &EmptyCB {}, &opt).await?; let result = render_json_value_raw(v, &vars, &EmptyCB {}, &opt).await?;
assert_eq!(result, json!(["aaa", "aaa"])); assert_eq!(result, json!(["aaa", "aaa"]));
@@ -619,9 +582,7 @@ mod render_json_value_raw_tests {
let v = json!({"${[a]}": "${[a]}"}); let v = json!({"${[a]}": "${[a]}"});
let mut vars = HashMap::new(); let mut vars = HashMap::new();
vars.insert("a".to_string(), "aaa".to_string()); vars.insert("a".to_string(), "aaa".to_string());
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
let result = render_json_value_raw(v, &vars, &EmptyCB {}, &opt).await?; let result = render_json_value_raw(v, &vars, &EmptyCB {}, &opt).await?;
assert_eq!(result, json!({"aaa": "aaa"})); assert_eq!(result, json!({"aaa": "aaa"}));
@@ -641,9 +602,7 @@ mod render_json_value_raw_tests {
]); ]);
let mut vars = HashMap::new(); let mut vars = HashMap::new();
vars.insert("a".to_string(), "aaa".to_string()); vars.insert("a".to_string(), "aaa".to_string());
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::Throw };
error_behavior: RenderErrorBehavior::Throw,
};
let result = render_json_value_raw(v, &vars, &EmptyCB {}, &opt).await?; let result = render_json_value_raw(v, &vars, &EmptyCB {}, &opt).await?;
assert_eq!( assert_eq!(
@@ -664,9 +623,7 @@ mod render_json_value_raw_tests {
#[tokio::test] #[tokio::test]
async fn render_opt_return_empty() -> Result<()> { async fn render_opt_return_empty() -> Result<()> {
let vars = HashMap::new(); let vars = HashMap::new();
let opt = RenderOptions { let opt = RenderOptions { error_behavior: RenderErrorBehavior::ReturnEmpty };
error_behavior: RenderErrorBehavior::ReturnEmpty,
};
let result = parse_and_render("DNE: ${[hello]}", &vars, &EmptyCB {}, &opt).await?; let result = parse_and_render("DNE: ${[hello]}", &vars, &EmptyCB {}, &opt).await?;
assert_eq!(result, "DNE: ".to_string()); assert_eq!(result, "DNE: ".to_string());
+2 -2
View File
@@ -1,7 +1,7 @@
use crate::error::Result; use crate::error::Result;
use crate::{escape, Parser}; use crate::{Parser, escape};
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue; use wasm_bindgen::JsValue;
use wasm_bindgen::prelude::wasm_bindgen;
#[wasm_bindgen] #[wasm_bindgen]
pub fn parse_template(template: &str) -> Result<JsValue> { pub fn parse_template(template: &str) -> Result<JsValue> {
+4 -14
View File
@@ -128,9 +128,7 @@ pub(crate) async fn send<R: Runtime>(
&PluginContext::new(&window), &PluginContext::new(&window),
RenderPurpose::Send, RenderPurpose::Send,
), ),
&RenderOptions { &RenderOptions { error_behavior: RenderErrorBehavior::Throw },
error_behavior: RenderErrorBehavior::Throw,
},
) )
.await?; .await?;
@@ -164,10 +162,7 @@ pub(crate) async fn close<R: Runtime>(
let db = app_handle.db(); let db = app_handle.db();
let connection = db.get_websocket_connection(connection_id)?; let connection = db.get_websocket_connection(connection_id)?;
db.upsert_websocket_connection( db.upsert_websocket_connection(
&WebsocketConnection { &WebsocketConnection { state: WebsocketConnectionState::Closing, ..connection },
state: WebsocketConnectionState::Closing,
..connection
},
&UpdateSource::from_window(&window), &UpdateSource::from_window(&window),
)? )?
}; };
@@ -208,9 +203,7 @@ pub(crate) async fn connect<R: Runtime>(
&PluginContext::new(&window), &PluginContext::new(&window),
RenderPurpose::Send, RenderPurpose::Send,
), ),
&RenderOptions { &RenderOptions { error_behavior: RenderErrorBehavior::Throw },
error_behavior: RenderErrorBehavior::Throw,
},
) )
.await?; .await?;
@@ -278,10 +271,7 @@ pub(crate) async fn connect<R: Runtime>(
.headers .headers
.clone() .clone()
.into_iter() .into_iter()
.map(|h| HttpHeader { .map(|h| HttpHeader { name: h.name, value: h.value })
name: h.name,
value: h.value,
})
.collect(), .collect(),
}; };
let plugin_result = plugin_manager let plugin_result = plugin_manager
+1 -1
View File
@@ -11,7 +11,7 @@ use crate::commands::{
}; };
use crate::manager::WebsocketManager; use crate::manager::WebsocketManager;
use tauri::plugin::{Builder, TauriPlugin}; use tauri::plugin::{Builder, TauriPlugin};
use tauri::{generate_handler, Manager, Runtime}; use tauri::{Manager, Runtime, generate_handler};
use tokio::sync::Mutex; use tokio::sync::Mutex;
pub fn init<R: Runtime>() -> TauriPlugin<R> { pub fn init<R: Runtime>() -> TauriPlugin<R> {
+1 -4
View File
@@ -23,10 +23,7 @@ pub struct WebsocketManager {
impl WebsocketManager { impl WebsocketManager {
pub fn new() -> Self { pub fn new() -> Self {
WebsocketManager { WebsocketManager { connections: Default::default(), read_tasks: Default::default() }
connections: Default::default(),
read_tasks: Default::default(),
}
} }
pub async fn connect( pub async fn connect(
+1 -8
View File
@@ -70,12 +70,5 @@ pub async fn render_websocket_request<T: TemplateCallback>(
let message = parse_and_render(&r.message.clone(), vars, cb, opt).await?; let message = parse_and_render(&r.message.clone(), vars, cb, opt).await?;
Ok(WebsocketRequest { Ok(WebsocketRequest { url, url_parameters, headers, authentication, message, ..r.to_owned() })
url,
url_parameters,
headers,
authentication,
message,
..r.to_owned()
})
} }