feat(cli): expose a function to kill dev child

This commit is contained in:
amrbashir
2023-01-28 04:33:19 +02:00
parent e3bfb01411
commit 7b8c23aa37
10 changed files with 63 additions and 7 deletions

View File

@@ -0,0 +1,5 @@
---
"cli.js": "minor"
---
Add `killDevApp` API to kill the dev app process manually.

View File

@@ -0,0 +1,5 @@
---
"cli.rs": "minor"
---
Add `tauri_cli::kill_dev_app` API to kill the dev app process manually.

View File

@@ -4,4 +4,5 @@
/* auto-generated by NAPI-RS */
export function run(args: Array<string>, binName: string | undefined | null, callback: (...args: any[]) => any): void
export function killDevApp(callback: (...args: any[]) => any): void
export function logError(error: string): void

View File

@@ -252,7 +252,8 @@ if (!nativeBinding) {
throw new Error(`Failed to load native binding`)
}
const { run, logError } = nativeBinding
const { run, killDevApp, logError } = nativeBinding
module.exports.run = run
module.exports.killDevApp = killDevApp
module.exports.logError = logError

View File

@@ -6,3 +6,4 @@
/* eslint-disable */
export function run(args: Array<string>, binName: string | undefined | null): Promise<void>
export function killDevApp(): Promise<void>

View File

@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
const { run, logError } = require('./index')
const { run, killDevApp, logError } = require('./index')
module.exports.run = (args, binName) => {
return new Promise((resolve, reject) => {
@@ -16,4 +16,16 @@ module.exports.run = (args, binName) => {
})
}
module.exports.killDevApp = () => {
return new Promise((resolve, reject) => {
killDevApp(res => {
if (res instanceof Error) {
reject(res)
} else {
resolve(res)
}
})
})
}
module.exports.logError = logError

View File

@@ -25,6 +25,23 @@ pub fn run(args: Vec<String>, bin_name: Option<String>, callback: JsFunction) ->
Ok(())
}
#[napi_derive::napi]
pub fn kill_dev_app(callback: JsFunction) -> Result<()> {
let function: ThreadsafeFunction<bool, ErrorStrategy::CalleeHandled> = callback
.create_threadsafe_function(0, |ctx| ctx.env.get_boolean(ctx.value).map(|v| vec![v]))?;
// we need to run in a separate thread so Node.js (e.g. vue-cli-plugin-tauri) consumers
// can do work while `tauri dev` is running.
std::thread::spawn(move || match tauri_cli::kill_dev_app() {
Ok(_) => function.call(Ok(true), ThreadsafeFunctionCallMode::Blocking),
Err(e) => function.call(
Err(Error::new(Status::GenericFailure, format!("{:#}", e))),
ThreadsafeFunctionCallMode::Blocking,
),
});
Ok(())
}
#[napi_derive::napi]
pub fn log_error(error: String) {
log::error!("{}", error);

View File

@@ -8,7 +8,7 @@ use crate::{
command_env,
config::{get as get_config, reload as reload_config, AppUrl, BeforeDevCommand, WindowUrl},
},
interface::{AppInterface, ExitReason, Interface},
interface::{rust::DevChild, AppInterface, ExitReason, Interface},
CommandExt, Result,
};
use clap::{ArgAction, Parser};
@@ -27,6 +27,7 @@ use std::{
},
};
pub(crate) static DEV_CHILD: OnceCell<Arc<Mutex<DevChild>>> = OnceCell::new();
static BEFORE_DEV: OnceCell<Mutex<Arc<SharedChild>>> = OnceCell::new();
static KILL_BEFORE_DEV_FLAG: OnceCell<AtomicBool> = OnceCell::new();

View File

@@ -91,7 +91,7 @@ pub struct DevChild {
}
impl DevChild {
fn kill(&self) -> std::io::Result<()> {
pub fn kill(&self) -> std::io::Result<()> {
if let Some(child) = &*self.app_child.lock().unwrap() {
child.kill()?;
} else {
@@ -194,11 +194,13 @@ impl Interface for Rust {
if options.no_watch {
let (tx, rx) = sync_channel(1);
self.run_dev(options, move |status, reason| {
let child = self.run_dev(options, move |status, reason| {
tx.send(()).unwrap();
on_exit_(status, reason)
})?;
let _ = crate::dev::DEV_CHILD.set(Arc::new(Mutex::new(child)));
rx.recv().unwrap();
Ok(())
} else {
@@ -206,6 +208,10 @@ impl Interface for Rust {
on_exit_(status, reason)
})?;
let child = Arc::new(Mutex::new(child));
let child_ = Arc::clone(&child);
let _ = crate::dev::DEV_CHILD.set(child_);
self.run_dev_watcher(child, options, on_exit)
}
}
@@ -392,11 +398,10 @@ impl Rust {
fn run_dev_watcher<F: Fn(ExitStatus, ExitReason) + Send + Sync + 'static>(
&mut self,
child: DevChild,
process: Arc<Mutex<DevChild>>,
options: Options,
on_exit: Arc<F>,
) -> crate::Result<()> {
let process = Arc::new(Mutex::new(child));
let (tx, rx) = sync_channel(1);
let app_path = app_dir();
let tauri_path = tauri_dir();

View File

@@ -176,6 +176,14 @@ where
Ok(())
}
pub fn kill_dev_app() -> Result<()> {
dev::DEV_CHILD
.get()
.map(|child| child.lock().unwrap().kill())
.unwrap_or(Ok(()))
.map_err(Into::into)
}
/// This maps the occurrence of `--verbose` flags to the correct log level
fn verbosity_level(num: u8) -> Level {
match num {