feat(cli): automate API -> plugin migration (#7561)

This commit is contained in:
Lucas Fernandes Nogueira 2023-08-08 09:21:46 -07:00 committed by GitHub
parent d010bc07b8
commit 8af2497496
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 152 additions and 4 deletions

View File

@ -0,0 +1,6 @@
---
"tauri-cli": patch:feat
"@tauri-apps/cli": patch:feat
---
The `migrate` command now automatically reads all JavaScript files and updates `@tauri-apps/api` import paths and install the missing plugins.

View File

@ -18,7 +18,7 @@ use tauri_utils::config::parse::{
const TAURI_GITIGNORE: &[u8] = include_bytes!("../../tauri.gitignore");
fn lookup<F: Fn(&PathBuf) -> bool>(dir: &Path, checker: F) -> Option<PathBuf> {
pub fn walk_builder(path: &Path) -> WalkBuilder {
let mut default_gitignore = std::env::temp_dir();
default_gitignore.push(".gitignore");
if !default_gitignore.exists() {
@ -28,9 +28,14 @@ fn lookup<F: Fn(&PathBuf) -> bool>(dir: &Path, checker: F) -> Option<PathBuf> {
}
}
let mut builder = WalkBuilder::new(dir);
let mut builder = WalkBuilder::new(path);
builder.add_custom_ignore_filename(".taurignore");
let _ = builder.add_ignore(default_gitignore);
builder
}
fn lookup<F: Fn(&PathBuf) -> bool>(dir: &Path, checker: F) -> Option<PathBuf> {
let mut builder = walk_builder(dir);
builder
.require_git(false)
.ignore(false)

View File

@ -2,7 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use std::{fmt::Display, path::Path};
use crate::{helpers::cross_command, Result};
use std::{fmt::Display, path::Path, process::ExitStatus};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PackageManager {
@ -65,4 +66,41 @@ impl PackageManager {
found
}
pub fn install(&self, dependencies: &[String]) -> Result<ExitStatus> {
match self {
PackageManager::Yarn => {
let mut cmd = cross_command("yarn");
cmd
.arg("add")
.args(dependencies)
.status()
.map_err(Into::into)
}
PackageManager::YarnBerry => {
let mut cmd = cross_command("yarn");
cmd
.arg("add")
.args(dependencies)
.status()
.map_err(Into::into)
}
PackageManager::Npm => {
let mut cmd = cross_command("npm");
cmd
.arg("install")
.args(dependencies)
.status()
.map_err(Into::into)
}
PackageManager::Pnpm => {
let mut cmd = cross_command("pnpm");
cmd
.arg("install")
.args(dependencies)
.status()
.map_err(Into::into)
}
}
}
}

View File

@ -0,0 +1,93 @@
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use crate::{
helpers::{app_paths::walk_builder, npm::PackageManager},
Result,
};
use std::{
fs::{read_to_string, write},
path::Path,
process::Command,
};
const CORE_API_MODULES: &[&str] = &["event", "path", "tauri", "mocks"];
const JS_EXTENSIONS: &[&str] = &["js", "jsx", "ts", "tsx", "mjs"];
pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
let mut new_npm_packages = Vec::new();
let mut new_cargo_packages = Vec::new();
let pm = PackageManager::from_project(app_dir)
.into_iter()
.next()
.unwrap_or(PackageManager::Npm);
let tauri_api_import_regex = regex::Regex::new(r"@tauri-apps/api/(\w+)").unwrap();
for entry in walk_builder(app_dir).build().flatten() {
if entry.file_type().map(|t| t.is_file()).unwrap_or_default() {
let path = entry.path();
let ext = path.extension().unwrap_or_default();
if JS_EXTENSIONS.iter().any(|e| e == &ext) {
let js_contents = read_to_string(path)?;
let new_contents =
tauri_api_import_regex.replace_all(&js_contents, |cap: &regex::Captures<'_>| {
let module = cap.get(1).unwrap().as_str();
let original = cap.get(0).unwrap().as_str();
if CORE_API_MODULES.contains(&module) {
original.to_string()
} else {
let plugin = format!("@tauri-apps/plugin-{module}");
log::info!(
"Replacing `{original}` with `{plugin}` on {}",
path.display()
);
new_npm_packages.push(plugin.clone());
new_cargo_packages.push(format!(
"tauri-plugin-{}",
if module == "clipboard" {
"clipboard-manager"
} else {
module
}
));
plugin
}
});
if new_contents != js_contents {
write(path, new_contents.as_bytes())?;
}
}
}
}
if !new_npm_packages.is_empty() {
log::info!(
"Installing NPM packages for plugins: {}",
new_npm_packages.join(", ")
);
pm.install(&new_npm_packages)?;
}
if !new_cargo_packages.is_empty() {
log::info!(
"Installing Cargo dependencies for plugins: {}",
new_cargo_packages.join(", ")
);
Command::new("cargo")
.arg("add")
.args(new_cargo_packages)
.current_dir(tauri_dir)
.status()?;
}
Ok(())
}

View File

@ -2,16 +2,22 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use crate::{helpers::app_paths::tauri_dir, Result};
use crate::{
helpers::app_paths::{app_dir, tauri_dir},
Result,
};
mod config;
mod frontend;
mod manifest;
pub fn command() -> Result<()> {
let tauri_dir = tauri_dir();
let app_dir = app_dir();
config::migrate(&tauri_dir)?;
manifest::migrate(&tauri_dir)?;
frontend::migrate(app_dir, &tauri_dir)?;
Ok(())
}