浏览代码

feat(cli): add deno support (#11304)

* feat(cli): add deno support

ref: https://github.com/denoland/deno/issues/20738

* Update packages_nodejs.rs

* typo

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
Amr Bashir 9 月之前
父节点
当前提交
b3563e3d6a

+ 6 - 0
.changes/deno.md

@@ -0,0 +1,6 @@
+---
+"tauri-cli": "patch:feat"
+"@tauri-apps/cli": "patch:feat"
+---
+
+Add Deno support in tauri-cli operations.

+ 4 - 3
crates/tauri-cli/src/add.rs

@@ -93,9 +93,10 @@ pub fn run(options: Options) -> Result<()> {
         }));
 
       let npm_spec = match (npm_version_req, options.tag, options.rev, options.branch) {
-        (Some(version), _, _, _) => {
-          format!("{npm_name}@{version}")
-        }
+        (Some(version_req), _, _, _) => match manager {
+          PackageManager::Deno => format!("npm:{npm_name}@{version_req}"),
+          _ => format!("{npm_name}@{version_req}"),
+        },
         (None, Some(tag), None, None) => {
           format!("tauri-apps/tauri-plugin-{plugin}#{tag}")
         }

+ 10 - 4
crates/tauri-cli/src/completions.rs

@@ -9,7 +9,7 @@ use clap_complete::{generate, Shell};
 
 use std::{fs::write, path::PathBuf};
 
-const PKG_MANAGERS: &[&str] = &["cargo", "pnpm", "npm", "yarn", "bun"];
+const PKG_MANAGERS: &[&str] = &["cargo", "pnpm", "npm", "yarn", "bun", "deno"];
 
 #[derive(Debug, Clone, Parser)]
 #[clap(about = "Generate Tauri CLI shell completions for Bash, Zsh, PowerShell or Fish")]
@@ -28,6 +28,10 @@ fn completions_for(shell: Shell, manager: &'static str, cmd: Command) -> Vec<u8>
     Command::new(manager)
       .bin_name(manager)
       .subcommand(Command::new("run").subcommand(tauri))
+  } else if manager == "deno" {
+    Command::new(manager)
+      .bin_name(manager)
+      .subcommand(Command::new("task").subcommand(tauri))
   } else {
     Command::new(manager).bin_name(manager).subcommand(tauri)
   };
@@ -41,13 +45,15 @@ fn get_completions(shell: Shell, cmd: Command) -> Result<String> {
   let completions = if shell == Shell::Bash {
     let mut completions =
       String::from_utf8_lossy(&completions_for(shell, "cargo", cmd)).into_owned();
-    for manager in PKG_MANAGERS {
+    for &manager in PKG_MANAGERS {
       completions.push_str(&format!(
         "complete -F _cargo -o bashdefault -o default {} tauri\n",
-        if manager == &"npm" {
+        if manager == "npm" {
           "npm run"
-        } else if manager == &"bun" {
+        } else if manager == "bun" {
           "bun run"
+        } else if manager == "deno" {
+          "deno task"
         } else {
           manager
         }

+ 12 - 38
crates/tauri-cli/src/helpers/npm.rs

@@ -14,6 +14,7 @@ pub enum PackageManager {
   Yarn,
   YarnBerry,
   Bun,
+  Deno,
 }
 
 impl Display for PackageManager {
@@ -27,6 +28,7 @@ impl Display for PackageManager {
         PackageManager::Yarn => "yarn",
         PackageManager::YarnBerry => "yarn berry",
         PackageManager::Bun => "bun",
+        PackageManager::Deno => "deno",
       }
     )
   }
@@ -34,46 +36,26 @@ impl Display for PackageManager {
 
 impl PackageManager {
   pub fn from_project<P: AsRef<Path>>(path: P) -> Vec<Self> {
-    let mut use_npm = false;
-    let mut use_pnpm = false;
-    let mut use_yarn = false;
-    let mut use_bun = false;
+    let mut found = Vec::new();
 
     if let Ok(entries) = std::fs::read_dir(path) {
       for entry in entries.flatten() {
         let path = entry.path();
         let name = path.file_name().unwrap().to_string_lossy();
         if name.as_ref() == "package-lock.json" {
-          use_npm = true;
+          found.push(PackageManager::Npm);
         } else if name.as_ref() == "pnpm-lock.yaml" {
-          use_pnpm = true;
+          found.push(PackageManager::Pnpm);
         } else if name.as_ref() == "yarn.lock" {
-          use_yarn = true;
+          found.push(PackageManager::Yarn);
         } else if name.as_ref() == "bun.lockb" {
-          use_bun = true;
+          found.push(PackageManager::Bun);
+        } else if name.as_ref() == "deno.lock" {
+          found.push(PackageManager::Deno);
         }
       }
     }
 
-    if !use_npm && !use_pnpm && !use_yarn && !use_bun {
-      return Vec::new();
-    }
-
-    let mut found = Vec::new();
-
-    if use_npm {
-      found.push(PackageManager::Npm);
-    }
-    if use_pnpm {
-      found.push(PackageManager::Pnpm);
-    }
-    if use_yarn {
-      found.push(PackageManager::Yarn);
-    }
-    if use_bun {
-      found.push(PackageManager::Bun);
-    }
-
     found
   }
 
@@ -84,6 +66,7 @@ impl PackageManager {
       PackageManager::Npm => cross_command("npm"),
       PackageManager::Pnpm => cross_command("pnpm"),
       PackageManager::Bun => cross_command("bun"),
+      PackageManager::Deno => cross_command("deno"),
     }
   }
 
@@ -175,15 +158,6 @@ impl PackageManager {
           .output()?,
         Some(regex::Regex::new("\"Version\":\"([\\da-zA-Z\\-\\.]+)\"").unwrap()),
       ),
-      PackageManager::Npm => (
-        cross_command("npm")
-          .arg("list")
-          .arg(name)
-          .args(["version", "--depth", "0"])
-          .current_dir(app_dir)
-          .output()?,
-        None,
-      ),
       PackageManager::Pnpm => (
         cross_command("pnpm")
           .arg("list")
@@ -193,8 +167,8 @@ impl PackageManager {
           .output()?,
         None,
       ),
-      // Bun doesn't support `list` command
-      PackageManager::Bun => (
+      // Bun and Deno don't support `list` command
+      PackageManager::Npm | PackageManager::Bun | PackageManager::Deno => (
         cross_command("npm")
           .arg("list")
           .arg(name)

+ 5 - 12
crates/tauri-cli/src/info/env_nodejs.rs

@@ -62,17 +62,10 @@ pub fn items(metadata: &VersionMetadata) -> Vec<SectionItem> {
         .ok()
         .unwrap_or_default()
     }),
-    SectionItem::new().action(|| {
-      manager_version("pnpm")
-        .map(|v| format!("pnpm: {}", v))
-        .into()
-    }),
-    SectionItem::new().action(|| {
-      manager_version("yarn")
-        .map(|v| format!("yarn: {}", v))
-        .into()
-    }),
-    SectionItem::new().action(|| manager_version("npm").map(|v| format!("npm: {}", v)).into()),
-    SectionItem::new().action(|| manager_version("bun").map(|v| format!("bun: {}", v)).into()),
+    SectionItem::new().action(|| manager_version("pnpm").map(|v| format!("pnpm: {v}")).into()),
+    SectionItem::new().action(|| manager_version("yarn").map(|v| format!("yarn: {v}")).into()),
+    SectionItem::new().action(|| manager_version("npm").map(|v| format!("npm: {v}")).into()),
+    SectionItem::new().action(|| manager_version("bun").map(|v| format!("bun: {v}")).into()),
+    SectionItem::new().action(|| manager_version("deno").map(|v| format!("deno: {v}")).into()),
   ]
 }

+ 11 - 58
crates/tauri-cli/src/info/packages_nodejs.rs

@@ -50,7 +50,8 @@ pub fn npm_latest_version(pm: &PackageManager, name: &str) -> crate::Result<Opti
         Ok(None)
       }
     }
-    PackageManager::Npm => {
+    // Bun and Deno don't support show command
+    PackageManager::Npm | PackageManager::Deno | PackageManager::Bun => {
       let mut cmd = cross_command("npm");
 
       let output = cmd.arg("show").arg(name).arg("version").output()?;
@@ -72,41 +73,13 @@ pub fn npm_latest_version(pm: &PackageManager, name: &str) -> crate::Result<Opti
         Ok(None)
       }
     }
-    // Bun doesn't support `info` command
-    PackageManager::Bun => {
-      let mut cmd = cross_command("npm");
-
-      let output = cmd.arg("show").arg(name).arg("version").output()?;
-      if output.status.success() {
-        let stdout = String::from_utf8_lossy(&output.stdout);
-        Ok(Some(stdout.replace('\n', "")))
-      } else {
-        Ok(None)
-      }
-    }
   }
 }
 
 pub fn package_manager(app_dir: &PathBuf) -> PackageManager {
-  let mut use_npm = false;
-  let mut use_pnpm = false;
-  let mut use_yarn = false;
-  let mut use_bun = false;
-
-  for entry in std::fs::read_dir(app_dir)
-    .unwrap()
-    .map(|e| e.unwrap().file_name().to_string_lossy().into_owned())
-  {
-    match entry.as_str() {
-      "pnpm-lock.yaml" => use_pnpm = true,
-      "package-lock.json" => use_npm = true,
-      "yarn.lock" => use_yarn = true,
-      "bun.lockb" => use_bun = true,
-      _ => {}
-    }
-  }
+  let found = PackageManager::from_project(app_dir);
 
-  if !use_npm && !use_pnpm && !use_yarn && !use_bun {
+  if found.is_empty() {
     println!(
       "{}: no lock files found, defaulting to npm",
       "WARNING".yellow()
@@ -114,45 +87,25 @@ pub fn package_manager(app_dir: &PathBuf) -> PackageManager {
     return PackageManager::Npm;
   }
 
-  let mut found = Vec::new();
-
-  if use_npm {
-    found.push(PackageManager::Npm);
-  }
-  if use_pnpm {
-    found.push(PackageManager::Pnpm);
-  }
-  if use_yarn {
-    found.push(PackageManager::Yarn);
-  }
-  if use_bun {
-    found.push(PackageManager::Bun);
-  }
+  let pkg_manager = found[0];
 
   if found.len() > 1 {
-    let pkg_manger = found[0];
     println!(
           "{}: Only one package manager should be used, but found {}.\n         Please remove unused package manager lock files, will use {} for now!",
           "WARNING".yellow(),
           found.iter().map(ToString::to_string).collect::<Vec<_>>().join(" and "),
-          pkg_manger
+          pkg_manager
         );
-    return pkg_manger;
   }
 
-  if use_npm {
-    PackageManager::Npm
-  } else if use_pnpm {
-    PackageManager::Pnpm
-  } else if use_bun {
-    PackageManager::Bun
-  } else if manager_version("yarn")
-    .map(|v| v.chars().next().map(|c| c > '1').unwrap_or_default())
-    .unwrap_or(false)
+  if pkg_manager == PackageManager::Yarn
+    && manager_version("yarn")
+      .map(|v| v.chars().next().map(|c| c > '1').unwrap_or_default())
+      .unwrap_or(false)
   {
     PackageManager::YarnBerry
   } else {
-    PackageManager::Yarn
+    pkg_manager
   }
 }
 

+ 2 - 0
crates/tauri-cli/src/init.rs

@@ -171,6 +171,7 @@ fn default_dev_command(pm: PackageManager) -> &'static str {
     PackageManager::Npm => "npm run dev",
     PackageManager::Pnpm => "pnpm dev",
     PackageManager::Bun => "bun dev",
+    PackageManager::Deno => "deno task dev",
   }
 }
 
@@ -181,6 +182,7 @@ fn default_build_command(pm: PackageManager) -> &'static str {
     PackageManager::Npm => "npm run build",
     PackageManager::Pnpm => "pnpm build",
     PackageManager::Bun => "bun build",
+    PackageManager::Deno => "deno task build",
   }
 }
 

+ 3 - 0
crates/tauri-cli/src/mobile/init.rs

@@ -90,6 +90,9 @@ pub fn exec(
 
             return (binary, build_args);
           }
+        } else if bin_stem == "deno" {
+          build_args.insert(0, "task");
+          return (std::ffi::OsString::from("deno"), build_args);
         } else if !cfg!(debug_assertions) && bin_stem == "cargo-tauri" {
           return (std::ffi::OsString::from("cargo"), build_args);
         }

+ 3 - 3
packages/cli/tauri.js

@@ -14,9 +14,9 @@ const binStem = path.parse(bin).name.toLowerCase()
 // can successfully detect what command likely started the execution.
 let binName
 
-// deno run -A --unstable --node-modules-dir npm:@tauri-apps/cli
-if (bin === '@tauri-apps/cli') {
-  binName = '@tauri-apps/cli'
+// deno run -A npm:@tauri-apps/cli or deno task tauri
+if (globalThis.navigator?.userAgent?.includes('Deno')) {
+  binName = bin
 }
 // Even if started by a package manager, the binary will be NodeJS.
 // Some distribution still use "nodejs" as the binary name.