diff --git a/.taurignore b/.taurignore index 28a49db3e..3c06c4ba4 100644 --- a/.taurignore +++ b/.taurignore @@ -1,2 +1,3 @@ plugins/*/permissions/autogenerated/ plugins/*/android/.tauri/tauri-api/build/ +plugins/*/android/build/intermediates/ diff --git a/Cargo.lock b/Cargo.lock index 82cabcc80..676c88795 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,6 +117,20 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android-keyring" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b051e1fab4f4c15e384424252c57321173b8fb274d50f30bd46145c35cd0a6a2" +dependencies = [ + "base64 0.22.1", + "jni", + "keyring", + "ndk-context", + "thiserror 2.0.12", + "tracing", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -301,7 +315,7 @@ dependencies = [ "objc2-foundation 0.3.0", "parking_lot", "percent-encoding", - "windows-sys 0.52.0", + "windows-sys 0.59.0", "wl-clipboard-rs", "x11rb", ] @@ -882,15 +896,6 @@ dependencies = [ "toml", ] -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - [[package]] name = "cc" version = "1.2.19" @@ -1054,7 +1059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -1419,36 +1424,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" -[[package]] -name = "dbus" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" -dependencies = [ - "libc", - "libdbus-sys", - "winapi", -] - -[[package]] -name = "dbus-secret-service" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" -dependencies = [ - "aes", - "block-padding", - "cbc", - "dbus", - "futures-util", - "hkdf", - "num", - "once_cell", - "openssl", - "rand 0.8.5", - "sha2", -] - [[package]] name = "deep-link-example" version = "0.0.0" @@ -1855,7 +1830,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3282,14 +3257,16 @@ dependencies = [ [[package]] name = "keyring" -version = "4.0.0-rc.2" -source = "git+https://github.com/open-source-cooperative/keyring-rs?rev=9635a2f53a19eb7f188cdc4e38982dcb19caee00#9635a2f53a19eb7f188cdc4e38982dcb19caee00" +version = "3.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c" dependencies = [ "byteorder", - "dbus-secret-service", + "linux-keyutils", "log", + "security-framework 2.11.1", "security-framework 3.2.0", - "windows-sys 0.59.0", + "windows-sys 0.60.2", "zeroize", ] @@ -3364,16 +3341,6 @@ version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" -[[package]] -name = "libdbus-sys" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "libflate" version = "2.1.0" @@ -3453,6 +3420,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-keyutils" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e" +dependencies = [ + "bitflags 2.9.0", + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -3834,30 +3811,6 @@ dependencies = [ "serde", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -3875,15 +3828,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -3910,17 +3854,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -4881,7 +4814,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5345,7 +5278,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5358,7 +5291,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6900,6 +6833,7 @@ dependencies = [ name = "tauri-plugin-secure-storage" version = "2.0.0" dependencies = [ + "android-keyring", "keyring", "log", "serde", @@ -7191,7 +7125,7 @@ dependencies = [ "getrandom 0.3.2", "once_cell", "rustix 1.0.5", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -8263,7 +8197,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/plugins/secure-storage/Cargo.toml b/plugins/secure-storage/Cargo.toml index f85c3b2da..6c1ab7662 100644 --- a/plugins/secure-storage/Cargo.toml +++ b/plugins/secure-storage/Cargo.toml @@ -15,26 +15,24 @@ rustdoc-args = ["--cfg", "docsrs"] # Support levels are "full", "partial", "none", "unknown" # Details of the support level are left to plugin maintainer [package.metadata.platforms] -windows = { level = "unknown", notes = "" } -linux = { level = "unknown", notes = "" } -macos = { level = "unknown", notes = "" } -android = { level = "unknown", notes = "" } -ios = { level = "unknown", notes = "" } - +windows = { level = "full", notes = "Windows' credentials storage only protects from other accounts on that system. The main user and their apps can access your app's data." } +linux = { level = "partial", notes = "For this PoC on Linux the storage is in-memory only and will be reset on reboot." } +macos = { level = "full", notes = "May prompt for passwords twice." } +android = { level = "full", notes = "The implementation is very new and therefore not battle-tested nor audited." } +ios = { level = "full", notes = "" } [build-dependencies] tauri-plugin = { workspace = true, features = ["build"] } -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] serde = { workspace = true } serde_json = { workspace = true } tauri = { workspace = true } log = { workspace = true } thiserror = { workspace = true } -# TODO: Non-android only: -keyring = { git = "https://github.com/open-source-cooperative/keyring-rs", rev = "9635a2f53a19eb7f188cdc4e38982dcb19caee00" } +# When updating to v4 we likely won't use linux-native aka keyutils but we need to look into which backend to use. +# Also, `linux-native` is non persistent. +keyring = { version = "3.6", features = ["apple-native", "windows-native", "linux-native"]} -[features] -vendored = ["keyring/vendored"] \ No newline at end of file +[target."cfg(target_os = \"android\")".dependencies] +android-keyring = "0.2.0" diff --git a/plugins/secure-storage/android/.gitignore b/plugins/secure-storage/android/.gitignore deleted file mode 100644 index c0f21ec2f..000000000 --- a/plugins/secure-storage/android/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/build -/.tauri diff --git a/plugins/secure-storage/android/build.gradle.kts b/plugins/secure-storage/android/build.gradle.kts deleted file mode 100644 index 1d0e9d8e8..000000000 --- a/plugins/secure-storage/android/build.gradle.kts +++ /dev/null @@ -1,44 +0,0 @@ -plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") -} - -android { - namespace = "{{android_package_id}}" - compileSdk = 34 - - defaultConfig { - minSdk = 24 - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = "1.8" - } -} - -dependencies { - - implementation("androidx.core:core-ktx:1.9.0") - implementation("androidx.appcompat:appcompat:1.6.0") - implementation("com.google.android.material:material:1.7.0") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") - implementation(project(":tauri-android")) -} diff --git a/plugins/secure-storage/android/proguard-rules.pro b/plugins/secure-storage/android/proguard-rules.pro deleted file mode 100644 index 481bb4348..000000000 --- a/plugins/secure-storage/android/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/plugins/secure-storage/android/settings.gradle b/plugins/secure-storage/android/settings.gradle deleted file mode 100644 index 14a752e43..000000000 --- a/plugins/secure-storage/android/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -include ':tauri-android' -project(':tauri-android').projectDir = new File('./.tauri/tauri-api') diff --git a/plugins/secure-storage/android/src/androidTest/java/ExampleInstrumentedTest.kt b/plugins/secure-storage/android/src/androidTest/java/ExampleInstrumentedTest.kt deleted file mode 100644 index b7ca3f668..000000000 --- a/plugins/secure-storage/android/src/androidTest/java/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2019-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -package {{android_package_id}} - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("{{android_package_id}}", appContext.packageName) - } -} diff --git a/plugins/secure-storage/android/src/main/AndroidManifest.xml b/plugins/secure-storage/android/src/main/AndroidManifest.xml deleted file mode 100644 index 9a40236b9..000000000 --- a/plugins/secure-storage/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/plugins/secure-storage/android/src/main/java/ExamplePlugin.kt b/plugins/secure-storage/android/src/main/java/ExamplePlugin.kt deleted file mode 100644 index 2f1729745..000000000 --- a/plugins/secure-storage/android/src/main/java/ExamplePlugin.kt +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2019-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -package {{android_package_id}} - -import android.app.Activity -import app.tauri.annotation.Command -import app.tauri.annotation.InvokeArg -import app.tauri.annotation.TauriPlugin -import app.tauri.plugin.JSObject -import app.tauri.plugin.Plugin -import app.tauri.plugin.Invoke - -@InvokeArg -class PingArgs { - var value: String? = null -} - -@TauriPlugin -class ExamplePlugin(private val activity: Activity): Plugin(activity) { - private val implementation = Example() - - @Command - fun ping(invoke: Invoke) { - val args = invoke.parseArgs(PingArgs::class.java) - - val ret = JSObject() - ret.put("value", implementation.pong(args.value ?: "default value :(")) - invoke.resolve(ret) - } -} diff --git a/plugins/secure-storage/android/src/test/java/ExampleUnitTest.kt b/plugins/secure-storage/android/src/test/java/ExampleUnitTest.kt deleted file mode 100644 index 71cee3c29..000000000 --- a/plugins/secure-storage/android/src/test/java/ExampleUnitTest.kt +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2019-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -package {{android_package_id}} - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} diff --git a/plugins/secure-storage/build.rs b/plugins/secure-storage/build.rs index 3a3eca52f..057fff8f2 100644 --- a/plugins/secure-storage/build.rs +++ b/plugins/secure-storage/build.rs @@ -7,7 +7,7 @@ const COMMANDS: &[&str] = &["set_string", "get_string", "set_binary", "get_binar fn main() { let result = tauri_plugin::Builder::new(COMMANDS) .global_api_script_path("./api-iife.js") - .android_path("android") + //.android_path("android") //.ios_path("ios") .try_build(); diff --git a/plugins/secure-storage/src/desktop.rs b/plugins/secure-storage/src/desktop.rs deleted file mode 100644 index 411c8b052..000000000 --- a/plugins/secure-storage/src/desktop.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2019-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -use keyring::Entry; -use serde::de::DeserializeOwned; -use tauri::{plugin::PluginApi, AppHandle, Runtime}; - -use crate::Result; - -pub fn init( - app: &AppHandle, - _api: PluginApi, -) -> crate::Result> { - Ok(SecureStorage(app.clone())) -} - -/// Access to the secure-storage APIs. -pub struct SecureStorage(AppHandle); - -impl SecureStorage { - pub fn set_string(&self, key: &str, value: &str) -> Result<()> { - Ok(Entry::new(&self.0.config().identifier, key)?.set_password(value)?) - } - - pub fn get_string(&self, key: &str) -> Result { - Ok(Entry::new(&self.0.config().identifier, key)?.get_password()?) - } - - pub fn set_binary(&self, key: &str, value: &[u8]) -> Result<()> { - Ok(Entry::new(&self.0.config().identifier, key)?.set_secret(value)?) - } - - pub fn get_binary(&self, key: &str) -> Result> { - Ok(Entry::new(&self.0.config().identifier, key)?.get_secret()?) - } -} diff --git a/plugins/secure-storage/src/error.rs b/plugins/secure-storage/src/error.rs index 5cb1fd10b..7af8ece59 100644 --- a/plugins/secure-storage/src/error.rs +++ b/plugins/secure-storage/src/error.rs @@ -8,12 +8,8 @@ pub type Result = std::result::Result; #[derive(Debug, thiserror::Error)] pub enum Error { - #[cfg(not(target_os = "android"))] #[error(transparent)] Keyring(#[from] keyring::Error), - #[cfg(target_os = "android")] - #[error(transparent)] - PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError), } impl Serialize for Error { diff --git a/plugins/secure-storage/src/lib.rs b/plugins/secure-storage/src/lib.rs index 378531588..7b2a88b78 100644 --- a/plugins/secure-storage/src/lib.rs +++ b/plugins/secure-storage/src/lib.rs @@ -2,29 +2,17 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT +use keyring::Entry; use tauri::{ plugin::{Builder, TauriPlugin}, - Manager, Runtime, + AppHandle, Manager, Runtime, }; -pub use models::*; - -#[cfg(not(target_os = "android"))] -mod desktop; -#[cfg(target_os = "android")] -mod mobile; - mod commands; mod error; -mod models; pub use error::{Error, Result}; -#[cfg(not(target_os = "android"))] -pub use desktop::SecureStorage; -#[cfg(target_os = "android")] -pub use mobile::SecureStorage; - // TODO: Consider using a worker thread to handle caveats mentioned by keyring-rs /// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the secure-storage APIs. @@ -47,13 +35,33 @@ pub fn init() -> TauriPlugin { commands::set_binary, commands::get_binary ]) - .setup(|app, api| { + .setup(|app, _api| { #[cfg(target_os = "android")] - let secure_storage = mobile::init(app, api)?; - #[cfg(not(target_os = "android"))] - let secure_storage = desktop::init(app, api)?; - app.manage(secure_storage); + android_keyring::set_android_keyring_credential_builder()?; + + app.manage(SecureStorage(app.clone())); Ok(()) }) .build() } + +/// Access to the secure-storage APIs. +pub struct SecureStorage(AppHandle); + +impl SecureStorage { + pub fn set_string(&self, key: &str, value: &str) -> Result<()> { + Ok(Entry::new(&self.0.config().identifier, key)?.set_password(value)?) + } + + pub fn get_string(&self, key: &str) -> Result { + Ok(Entry::new(&self.0.config().identifier, key)?.get_password()?) + } + + pub fn set_binary(&self, key: &str, value: &[u8]) -> Result<()> { + Ok(Entry::new(&self.0.config().identifier, key)?.set_secret(value)?) + } + + pub fn get_binary(&self, key: &str) -> Result> { + Ok(Entry::new(&self.0.config().identifier, key)?.get_secret()?) + } +} diff --git a/plugins/secure-storage/src/mobile.rs b/plugins/secure-storage/src/mobile.rs deleted file mode 100644 index e3a7e943f..000000000 --- a/plugins/secure-storage/src/mobile.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2019-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -use serde::de::DeserializeOwned; -use tauri::{ - plugin::{PluginApi, PluginHandle}, - AppHandle, Runtime, -}; - -use crate::models::*; - -#[cfg(target_os = "android")] -const PLUGIN_IDENTIFIER: &str = "app.tauri.secure_storage"; - -//#[cfg(target_os = "ios")] -//tauri::ios_plugin_binding!(init_plugin_secure_storage); - -// initializes the Kotlin or Swift plugin classes -pub fn init( - _app: &AppHandle, - api: PluginApi, -) -> crate::Result> { - #[cfg(target_os = "android")] - let handle = api.register_android_plugin(PLUGIN_IDENTIFIER, "ExamplePlugin")?; - //#[cfg(target_os = "ios")] - //let handle = api.register_ios_plugin(init_plugin_secure_storage)?; - Ok(SecureStorage(handle)) -} - -/// Access to the secure_storage APIs. -pub struct SecureStorage(PluginHandle); - -impl SecureStorage { - pub fn ping(&self, payload: PingRequest) -> crate::Result { - self.0 - .run_mobile_plugin("ping", payload) - .map_err(Into::into) - } -} diff --git a/plugins/secure-storage/src/models.rs b/plugins/secure-storage/src/models.rs deleted file mode 100644 index d50dcf915..000000000 --- a/plugins/secure-storage/src/models.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2019-2023 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct PingRequest { - pub value: Option, -} - -#[derive(Debug, Clone, Default, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PingResponse { - pub value: Option, -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1292a95b0..d5ccb1675 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2351,9 +2351,9 @@ snapshots: - encoding - mocha - '@covector/assemble@0.12.0': + '@covector/assemble@0.12.0(mocha@10.8.2)': dependencies: - '@covector/command': 0.8.0 + '@covector/command': 0.8.0(mocha@10.8.2) '@covector/files': 0.8.0 effection: 2.0.8(mocha@10.8.2) js-yaml: 4.1.0 @@ -2364,9 +2364,10 @@ snapshots: unified: 9.2.2 transitivePeerDependencies: - encoding + - mocha - supports-color - '@covector/changelog@0.12.0': + '@covector/changelog@0.12.0(mocha@10.8.2)': dependencies: '@covector/files': 0.8.0 effection: 2.0.8(mocha@10.8.2) @@ -2376,14 +2377,16 @@ snapshots: unified: 9.2.2 transitivePeerDependencies: - encoding + - mocha - supports-color - '@covector/command@0.8.0': + '@covector/command@0.8.0(mocha@10.8.2)': dependencies: - '@effection/process': 2.1.4 + '@effection/process': 2.1.4(mocha@10.8.2) effection: 2.0.8(mocha@10.8.2) transitivePeerDependencies: - encoding + - mocha '@covector/files@0.8.0': dependencies: @@ -2430,10 +2433,8 @@ snapshots: dependencies: effection: 2.0.8(mocha@10.8.2) mocha: 10.8.2 - transitivePeerDependencies: - - encoding - '@effection/process@2.1.4': + '@effection/process@2.1.4(mocha@10.8.2)': dependencies: cross-spawn: 7.0.6 ctrlc-windows: 2.2.0 @@ -2441,6 +2442,7 @@ snapshots: shellwords: 0.1.1 transitivePeerDependencies: - encoding + - mocha '@effection/stream@2.0.6': dependencies: @@ -3271,9 +3273,9 @@ snapshots: dependencies: '@clack/prompts': 0.7.0 '@covector/apply': 0.10.0(mocha@10.8.2) - '@covector/assemble': 0.12.0 - '@covector/changelog': 0.12.0 - '@covector/command': 0.8.0 + '@covector/assemble': 0.12.0(mocha@10.8.2) + '@covector/changelog': 0.12.0(mocha@10.8.2) + '@covector/command': 0.8.0(mocha@10.8.2) '@covector/files': 0.8.0 effection: 2.0.8(mocha@10.8.2) globby: 11.1.0