mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 09:18:30 +02:00
Embed CLI plugin assets and share bundled plugin registration
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -10149,6 +10149,7 @@ dependencies = [
|
|||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
"hex",
|
"hex",
|
||||||
|
"include_dir",
|
||||||
"keyring",
|
"keyring",
|
||||||
"log 0.4.29",
|
"log 0.4.29",
|
||||||
"oxc_resolver",
|
"oxc_resolver",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ dirs = "6"
|
|||||||
env_logger = "0.11"
|
env_logger = "0.11"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
hex = { workspace = true }
|
hex = { workspace = true }
|
||||||
|
include_dir = "0.7"
|
||||||
keyring = { workspace = true, features = ["apple-native", "windows-native", "sync-secret-service"] }
|
keyring = { workspace = true, features = ["apple-native", "windows-native", "sync-secret-service"] }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use crate::plugin_events::CliPluginEventBridge;
|
use crate::plugin_events::CliPluginEventBridge;
|
||||||
|
use include_dir::{Dir, include_dir};
|
||||||
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
@@ -9,6 +11,13 @@ use yaak_models::query_manager::QueryManager;
|
|||||||
use yaak_plugins::events::PluginContext;
|
use yaak_plugins::events::PluginContext;
|
||||||
use yaak_plugins::manager::PluginManager;
|
use yaak_plugins::manager::PluginManager;
|
||||||
|
|
||||||
|
const EMBEDDED_PLUGIN_RUNTIME: &str = include_str!(concat!(
|
||||||
|
env!("CARGO_MANIFEST_DIR"),
|
||||||
|
"/../../crates-tauri/yaak-app/vendored/plugin-runtime/index.cjs"
|
||||||
|
));
|
||||||
|
static EMBEDDED_VENDORED_PLUGINS: Dir<'_> =
|
||||||
|
include_dir!("$CARGO_MANIFEST_DIR/../../crates-tauri/yaak-app/vendored/plugins");
|
||||||
|
|
||||||
pub struct CliContext {
|
pub struct CliContext {
|
||||||
data_dir: PathBuf,
|
data_dir: PathBuf,
|
||||||
query_manager: QueryManager,
|
query_manager: QueryManager,
|
||||||
@@ -33,10 +42,13 @@ impl CliContext {
|
|||||||
let installed_plugin_dir = data_dir.join("installed-plugins");
|
let installed_plugin_dir = data_dir.join("installed-plugins");
|
||||||
let node_bin_path = PathBuf::from("node");
|
let node_bin_path = PathBuf::from("node");
|
||||||
|
|
||||||
|
prepare_embedded_vendored_plugins(&vendored_plugin_dir)
|
||||||
|
.expect("Failed to prepare bundled plugins");
|
||||||
|
|
||||||
let plugin_runtime_main =
|
let plugin_runtime_main =
|
||||||
std::env::var("YAAK_PLUGIN_RUNTIME").map(PathBuf::from).unwrap_or_else(|_| {
|
std::env::var("YAAK_PLUGIN_RUNTIME").map(PathBuf::from).unwrap_or_else(|_| {
|
||||||
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
prepare_embedded_plugin_runtime(&data_dir)
|
||||||
.join("../../crates-tauri/yaak-app/vendored/plugin-runtime/index.cjs")
|
.expect("Failed to prepare embedded plugin runtime")
|
||||||
});
|
});
|
||||||
|
|
||||||
let plugin_manager = Arc::new(
|
let plugin_manager = Arc::new(
|
||||||
@@ -50,6 +62,13 @@ impl CliContext {
|
|||||||
.await,
|
.await,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
let db = query_manager.connect();
|
||||||
|
if let Err(err) = plugin_manager.ensure_bundled_plugins_registered(&db).await {
|
||||||
|
eprintln!("Warning: Failed to register bundled plugins: {err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let plugins = query_manager.connect().list_plugins().unwrap_or_default();
|
let plugins = query_manager.connect().list_plugins().unwrap_or_default();
|
||||||
if !plugins.is_empty() {
|
if !plugins.is_empty() {
|
||||||
let errors = plugin_manager
|
let errors = plugin_manager
|
||||||
@@ -113,3 +132,17 @@ impl CliContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prepare_embedded_plugin_runtime(data_dir: &Path) -> std::io::Result<PathBuf> {
|
||||||
|
let runtime_dir = data_dir.join("vendored").join("plugin-runtime");
|
||||||
|
fs::create_dir_all(&runtime_dir)?;
|
||||||
|
let runtime_main = runtime_dir.join("index.cjs");
|
||||||
|
fs::write(&runtime_main, EMBEDDED_PLUGIN_RUNTIME)?;
|
||||||
|
Ok(runtime_main)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_embedded_vendored_plugins(vendored_plugin_dir: &Path) -> std::io::Result<()> {
|
||||||
|
fs::create_dir_all(vendored_plugin_dir)?;
|
||||||
|
EMBEDDED_VENDORED_PLUGINS.extract(vendored_plugin_dir)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ use tokio::sync::Mutex;
|
|||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
use yaak_api::yaak_api_client;
|
use yaak_api::yaak_api_client;
|
||||||
use yaak_models::models::Plugin;
|
use yaak_models::models::Plugin;
|
||||||
use yaak_models::util::UpdateSource;
|
|
||||||
use yaak_plugins::api::{
|
use yaak_plugins::api::{
|
||||||
PluginNameVersion, PluginSearchResponse, PluginUpdatesResponse, check_plugin_updates,
|
PluginNameVersion, PluginSearchResponse, PluginUpdatesResponse, check_plugin_updates,
|
||||||
search_plugins,
|
search_plugins,
|
||||||
@@ -281,28 +280,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Initialize all plugins after manager is created
|
|
||||||
let bundled_dirs = manager
|
|
||||||
.list_bundled_plugin_dirs()
|
|
||||||
.await
|
|
||||||
.expect("Failed to list bundled plugins");
|
|
||||||
|
|
||||||
// Ensure all bundled plugins make it into the database
|
|
||||||
let db = app_handle_clone.db();
|
let db = app_handle_clone.db();
|
||||||
for dir in &bundled_dirs {
|
manager
|
||||||
if db.get_plugin_by_directory(dir).is_none() {
|
.ensure_bundled_plugins_registered(&db)
|
||||||
db.upsert_plugin(
|
.await
|
||||||
&Plugin {
|
.expect("Failed to register bundled plugins");
|
||||||
directory: dir.clone(),
|
|
||||||
enabled: true,
|
|
||||||
url: None,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
&UpdateSource::Background,
|
|
||||||
)
|
|
||||||
.expect("Failed to upsert bundled plugin");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all plugins from database and initialize
|
// Get all plugins from database and initialize
|
||||||
let plugins = db.list_plugins().expect("Failed to list plugins from database");
|
let plugins = db.list_plugins().expect("Failed to list plugins from database");
|
||||||
|
|||||||
@@ -33,8 +33,9 @@ use tokio::net::TcpListener;
|
|||||||
use tokio::sync::mpsc::error::TrySendError;
|
use tokio::sync::mpsc::error::TrySendError;
|
||||||
use tokio::sync::{Mutex, mpsc, oneshot};
|
use tokio::sync::{Mutex, mpsc, oneshot};
|
||||||
use tokio::time::{Instant, timeout};
|
use tokio::time::{Instant, timeout};
|
||||||
|
use yaak_models::db_context::DbContext;
|
||||||
use yaak_models::models::Plugin;
|
use yaak_models::models::Plugin;
|
||||||
use yaak_models::util::generate_id;
|
use yaak_models::util::{UpdateSource, generate_id};
|
||||||
use yaak_templates::error::Error::RenderError;
|
use yaak_templates::error::Error::RenderError;
|
||||||
use yaak_templates::error::Result as TemplateResult;
|
use yaak_templates::error::Result as TemplateResult;
|
||||||
|
|
||||||
@@ -180,6 +181,33 @@ impl PluginManager {
|
|||||||
read_plugins_dir(&plugins_dir).await
|
read_plugins_dir(&plugins_dir).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ensure all bundled plugin directories are present in the plugins table.
|
||||||
|
/// Returns a list of newly registered plugin directories.
|
||||||
|
pub async fn ensure_bundled_plugins_registered(
|
||||||
|
&self,
|
||||||
|
db: &DbContext<'_>,
|
||||||
|
) -> Result<Vec<String>> {
|
||||||
|
let bundled_dirs = self.list_bundled_plugin_dirs().await?;
|
||||||
|
let mut registered = Vec::new();
|
||||||
|
|
||||||
|
for dir in bundled_dirs {
|
||||||
|
if db.get_plugin_by_directory(&dir).is_none() {
|
||||||
|
db.upsert_plugin(
|
||||||
|
&Plugin {
|
||||||
|
directory: dir.clone(),
|
||||||
|
enabled: true,
|
||||||
|
url: None,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&UpdateSource::Background,
|
||||||
|
)?;
|
||||||
|
registered.push(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(registered)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn uninstall(&self, plugin_context: &PluginContext, dir: &str) -> Result<()> {
|
pub async fn uninstall(&self, plugin_context: &PluginContext, dir: &str) -> Result<()> {
|
||||||
let plugin = self.get_plugin_by_dir(dir).await.ok_or(PluginNotFoundErr(dir.to_string()))?;
|
let plugin = self.get_plugin_by_dir(dir).await.ok_or(PluginNotFoundErr(dir.to_string()))?;
|
||||||
self.remove_plugin(plugin_context, &plugin).await
|
self.remove_plugin(plugin_context, &plugin).await
|
||||||
|
|||||||
Reference in New Issue
Block a user