mirror of https://github.com/tauri-apps/tauri
Closes #10596
This commit is contained in:
parent
712f1049fa
commit
f35bcda289
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
"tauri-cli": patch:enhance
|
||||
"@tauri-apps/cli": patch:enhance
|
||||
---
|
||||
|
||||
`permission add` and `add` commands now check if the plugin is known and if it is either desktop or mobile only
|
||||
we add the permission to a target-specific capability.
|
|
@ -31,14 +31,36 @@ impl TomlOrJson {
|
|||
}
|
||||
}
|
||||
|
||||
fn insert_permission(&mut self, idenitifer: String) {
|
||||
fn platforms(&self) -> Option<Vec<&str>> {
|
||||
match self {
|
||||
TomlOrJson::Toml(t) => t.get("platforms").and_then(|k| {
|
||||
k.as_array()
|
||||
.and_then(|array| array.iter().map(|v| v.as_str()).collect())
|
||||
}),
|
||||
TomlOrJson::Json(j) => j.get("platforms").and_then(|k| {
|
||||
if let Some(array) = k.as_array() {
|
||||
let mut items = Vec::new();
|
||||
for item in array {
|
||||
if let Some(s) = item.as_str() {
|
||||
items.push(s);
|
||||
}
|
||||
}
|
||||
Some(items)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_permission(&mut self, identifier: String) {
|
||||
match self {
|
||||
TomlOrJson::Toml(t) => {
|
||||
let permissions = t.entry("permissions").or_insert_with(|| {
|
||||
toml_edit::Item::Value(toml_edit::Value::Array(toml_edit::Array::new()))
|
||||
});
|
||||
if let Some(permissions) = permissions.as_array_mut() {
|
||||
permissions.push(idenitifer)
|
||||
permissions.push(identifier)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -48,7 +70,7 @@ impl TomlOrJson {
|
|||
.entry("permissions")
|
||||
.or_insert_with(|| serde_json::Value::Array(Vec::new()));
|
||||
if let Some(permissions) = permissions.as_array_mut() {
|
||||
permissions.push(serde_json::Value::String(idenitifer))
|
||||
permissions.push(serde_json::Value::String(identifier))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +122,13 @@ pub fn command(options: Options) -> Result<()> {
|
|||
);
|
||||
}
|
||||
|
||||
let capabilities = std::fs::read_dir(&capabilities_dir)?
|
||||
let known_plugins = crate::helpers::plugins::known_plugins();
|
||||
let known_plugin = options
|
||||
.identifier
|
||||
.split_once(':')
|
||||
.and_then(|(plugin, _permission)| known_plugins.get(&plugin));
|
||||
|
||||
let capabilities_iter = std::fs::read_dir(&capabilities_dir)?
|
||||
.flatten()
|
||||
.filter(|e| e.file_type().map(|e| e.is_file()).unwrap_or_default())
|
||||
.filter_map(|e| {
|
||||
|
@ -109,8 +137,66 @@ pub fn command(options: Options) -> Result<()> {
|
|||
Some(c) => (c == capability.identifier()).then_some((capability, path)),
|
||||
None => Some((capability, path)),
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
});
|
||||
|
||||
let (desktop_only, mobile_only) = known_plugin
|
||||
.map(|p| (p.desktop_only, p.mobile_only))
|
||||
.unwrap_or_default();
|
||||
|
||||
let expected_capability_config = if desktop_only {
|
||||
Some((
|
||||
vec![
|
||||
tauri_utils::platform::Target::MacOS.to_string(),
|
||||
tauri_utils::platform::Target::Windows.to_string(),
|
||||
tauri_utils::platform::Target::Linux.to_string(),
|
||||
],
|
||||
"desktop",
|
||||
))
|
||||
} else if mobile_only {
|
||||
Some((
|
||||
vec![
|
||||
tauri_utils::platform::Target::Android.to_string(),
|
||||
tauri_utils::platform::Target::Ios.to_string(),
|
||||
],
|
||||
"mobile",
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let capabilities = if let Some((expected_platforms, target_name)) = expected_capability_config {
|
||||
let mut capabilities = capabilities_iter
|
||||
.filter(|(capability, _path)| {
|
||||
capability.platforms().map_or(
|
||||
false, /* allows any target, so we should skip it since we're adding a target-specific plugin */
|
||||
|platforms| {
|
||||
// all platforms must be in the expected platforms list
|
||||
platforms.iter().all(|p| expected_platforms.contains(&p.to_string()))
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if capabilities.is_empty() {
|
||||
let identifier = format!("{target_name}-capability");
|
||||
let capability_path = capabilities_dir.join(target_name).with_extension("json");
|
||||
log::info!(
|
||||
"Capability matching platforms {expected_platforms:?} not found, creating {}",
|
||||
capability_path.display()
|
||||
);
|
||||
capabilities.push((
|
||||
TomlOrJson::Json(serde_json::json!({
|
||||
"identifier": identifier,
|
||||
"platforms": expected_platforms
|
||||
})),
|
||||
capability_path,
|
||||
));
|
||||
}
|
||||
|
||||
capabilities
|
||||
} else {
|
||||
capabilities_iter.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
let mut capabilities = if capabilities.len() > 1 {
|
||||
let selections = prompts::multiselect(
|
||||
|
@ -132,6 +218,11 @@ pub fn command(options: Options) -> Result<()> {
|
|||
.as_slice(),
|
||||
None,
|
||||
)?;
|
||||
|
||||
if selections.is_empty() {
|
||||
anyhow::bail!("You did not select any capabilities to update");
|
||||
}
|
||||
|
||||
selections
|
||||
.into_iter()
|
||||
.map(|idx| capabilities[idx].clone())
|
||||
|
@ -140,6 +231,10 @@ pub fn command(options: Options) -> Result<()> {
|
|||
capabilities
|
||||
};
|
||||
|
||||
if capabilities.is_empty() {
|
||||
anyhow::bail!("Could not find a capability to update");
|
||||
}
|
||||
|
||||
for (capability, path) in &mut capabilities {
|
||||
capability.insert_permission(options.identifier.clone());
|
||||
std::fs::write(&*path, capability.to_string()?)?;
|
||||
|
|
|
@ -16,61 +16,7 @@ use crate::{
|
|||
Result,
|
||||
};
|
||||
|
||||
use std::{collections::HashMap, process::Command};
|
||||
|
||||
#[derive(Default)]
|
||||
struct PluginMetadata {
|
||||
desktop_only: bool,
|
||||
mobile_only: bool,
|
||||
rust_only: bool,
|
||||
builder: bool,
|
||||
}
|
||||
|
||||
// known plugins with particular cases
|
||||
fn plugins() -> HashMap<&'static str, PluginMetadata> {
|
||||
let mut plugins: HashMap<&'static str, PluginMetadata> = HashMap::new();
|
||||
|
||||
// desktop-only
|
||||
for p in [
|
||||
"authenticator",
|
||||
"autostart",
|
||||
"cli",
|
||||
"global-shortcut",
|
||||
"positioner",
|
||||
"single-instance",
|
||||
"updater",
|
||||
"window-state",
|
||||
] {
|
||||
plugins.entry(p).or_default().desktop_only = true;
|
||||
}
|
||||
|
||||
// mobile-only
|
||||
for p in ["barcode-scanner", "biometric", "nfc"] {
|
||||
plugins.entry(p).or_default().mobile_only = true;
|
||||
}
|
||||
|
||||
// uses builder pattern
|
||||
for p in [
|
||||
"global-shortcut",
|
||||
"localhost",
|
||||
"log",
|
||||
"sql",
|
||||
"store",
|
||||
"stronghold",
|
||||
"updater",
|
||||
"window-state",
|
||||
] {
|
||||
plugins.entry(p).or_default().builder = true;
|
||||
}
|
||||
|
||||
// rust-only
|
||||
#[allow(clippy::single_element_loop)]
|
||||
for p in ["localhost", "persisted-scope", "single-instance"] {
|
||||
plugins.entry(p).or_default().rust_only = true;
|
||||
}
|
||||
|
||||
plugins
|
||||
}
|
||||
use std::process::Command;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(about = "Add a tauri plugin to the project")]
|
||||
|
@ -104,7 +50,7 @@ pub fn command(options: Options) -> Result<()> {
|
|||
let crate_name = format!("tauri-plugin-{plugin}");
|
||||
let npm_name = format!("@tauri-apps/plugin-{plugin}");
|
||||
|
||||
let mut plugins = plugins();
|
||||
let mut plugins = crate::helpers::plugins::known_plugins();
|
||||
let metadata = plugins.remove(plugin).unwrap_or_default();
|
||||
|
||||
let app_dir = resolve_app_dir();
|
||||
|
|
|
@ -9,6 +9,7 @@ pub mod config;
|
|||
pub mod flock;
|
||||
pub mod framework;
|
||||
pub mod npm;
|
||||
pub mod plugins;
|
||||
pub mod prompts;
|
||||
pub mod template;
|
||||
pub mod updater_signature;
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PluginMetadata {
|
||||
pub desktop_only: bool,
|
||||
pub mobile_only: bool,
|
||||
pub rust_only: bool,
|
||||
pub builder: bool,
|
||||
}
|
||||
|
||||
// known plugins with particular cases
|
||||
pub fn known_plugins() -> HashMap<&'static str, PluginMetadata> {
|
||||
let mut plugins: HashMap<&'static str, PluginMetadata> = HashMap::new();
|
||||
|
||||
// desktop-only
|
||||
for p in [
|
||||
"authenticator",
|
||||
"autostart",
|
||||
"cli",
|
||||
"global-shortcut",
|
||||
"positioner",
|
||||
"single-instance",
|
||||
"updater",
|
||||
"window-state",
|
||||
] {
|
||||
plugins.entry(p).or_default().desktop_only = true;
|
||||
}
|
||||
|
||||
// mobile-only
|
||||
for p in ["barcode-scanner", "biometric", "nfc", "haptics"] {
|
||||
plugins.entry(p).or_default().mobile_only = true;
|
||||
}
|
||||
|
||||
// uses builder pattern
|
||||
for p in [
|
||||
"global-shortcut",
|
||||
"localhost",
|
||||
"log",
|
||||
"sql",
|
||||
"store",
|
||||
"stronghold",
|
||||
"updater",
|
||||
"window-state",
|
||||
] {
|
||||
plugins.entry(p).or_default().builder = true;
|
||||
}
|
||||
|
||||
// rust-only
|
||||
#[allow(clippy::single_element_loop)]
|
||||
for p in ["localhost", "persisted-scope", "single-instance"] {
|
||||
plugins.entry(p).or_default().rust_only = true;
|
||||
}
|
||||
|
||||
plugins
|
||||
}
|
Loading…
Reference in New Issue