Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api.js): add nodejs-inspired functions in path module #2310

Merged
merged 20 commits into from
Aug 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changes/api-path-module.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"api": patch
---

- Add new nodejs-inspired functions which are `join`, `resolve`, `normalize`, `dirname`, `basename` and `extname`.
- Add `sep` and `delimiter` constants.
- Removed `resolvePath` API, use `resolve` instead.
5 changes: 3 additions & 2 deletions core/tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ api-all = [
"shell-all",
"os-all",
"dialog-all",
"updater"
"updater",
"path-all"
]
updater = [ "minisign-verify", "base64" ]
menu = [ "tauri-runtime/menu", "tauri-runtime-wry/menu" ]
Expand All @@ -117,7 +118,7 @@ fs-create-dir = [ ]
fs-remove-dir = [ ]
fs-remove-file = [ ]
fs-rename-file = [ ]
fs-path = [ ]
path-all = [ ]
window-all = [ ]
window-create = [ ]
shell-all = [ "shell-open", "shell-execute" ]
Expand Down
4 changes: 3 additions & 1 deletion core/tauri/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ fn main() {
fs_remove_dir: { any(fs_all, feature = "fs-remove-dir") },
fs_remove_file: { any(fs_all, feature = "fs-remove-file") },
fs_rename_file: { any(fs_all, feature = "fs-rename-file") },
fs_path: { any(fs_all, feature = "fs-path") },

// window
window_all: { any(api_all, feature = "window-all") },
Expand Down Expand Up @@ -54,5 +53,8 @@ fn main() {

// os
os_all: { any(api_all, feature = "os-all") },

// path
path_all: { any(api_all, feature = "path-all") },
}
}
2 changes: 1 addition & 1 deletion core/tauri/scripts/bundle.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions core/tauri/src/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod http;
mod internal;
mod notification;
mod operating_system;
mod path;
mod process;
mod shell;
mod window;
Expand All @@ -49,6 +50,7 @@ enum Module {
Process(process::Cmd),
Fs(file_system::Cmd),
Os(operating_system::Cmd),
Path(path::Cmd),
Window(Box<window::Cmd>),
Shell(shell::Cmd),
Event(event::Cmd),
Expand Down Expand Up @@ -84,6 +86,12 @@ impl Module {
.and_then(|r| r.json)
.map_err(InvokeError::from)
}),
Self::Path(cmd) => resolver.respond_async(async move {
cmd
.run(config, &package_info)
.and_then(|r| r.json)
.map_err(InvokeError::from)
}),
Self::Os(cmd) => resolver
.respond_async(async move { cmd.run().and_then(|r| r.json).map_err(InvokeError::from) }),
Self::Window(cmd) => resolver.respond_async(async move {
Expand Down
22 changes: 0 additions & 22 deletions core/tauri/src/endpoints/file_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,6 @@ pub enum Cmd {
new_path: PathBuf,
options: Option<FileOperationOptions>,
},
/// The resolve path API
ResolvePath {
path: String,
directory: Option<BaseDirectory>,
},
}

impl Cmd {
Expand Down Expand Up @@ -201,13 +196,6 @@ impl Cmd {
Self::RenameFile { .. } => Err(crate::Error::ApiNotAllowlisted(
"fs > renameFile".to_string(),
)),

#[cfg(fs_path)]
Self::ResolvePath { path, directory } => {
resolve_path_handler(&config, package_info, path, directory).map(Into::into)
}
#[cfg(not(fs_path))]
Self::ResolvePath { .. } => Err(crate::Error::ApiNotAllowlisted("fs > path".to_string())),
}
}
}
Expand Down Expand Up @@ -405,16 +393,6 @@ pub fn read_binary_file(
.map_err(crate::Error::FailedToExecuteApi)
}

#[cfg(fs_path)]
pub fn resolve_path_handler(
config: &Config,
package_info: &PackageInfo,
path: String,
directory: Option<BaseDirectory>,
) -> crate::Result<PathBuf> {
resolve_path(config, package_info, path, directory).map_err(Into::into)
}

// test webview functionality.
#[cfg(test)]
mod test {
Expand Down
156 changes: 156 additions & 0 deletions core/tauri/src/endpoints/path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

use super::InvokeResponse;
use crate::{api::path::BaseDirectory, Config, PackageInfo};
use serde::Deserialize;
#[cfg(path_all)]
use std::path::{Path, PathBuf};
use std::sync::Arc;
/// The API descriptor.
#[derive(Deserialize)]
#[serde(tag = "cmd", rename_all = "camelCase")]
pub enum Cmd {
ResolvePath {
path: String,
directory: Option<BaseDirectory>,
},
Resolve {
paths: Vec<String>,
},
Normalize {
path: String,
},
Join {
paths: Vec<String>,
},
Dirname {
path: String,
},
Extname {
path: String,
},
Basename {
path: String,
ext: Option<String>,
},
IsAbsolute {
path: String,
},
}

impl Cmd {
#[allow(unused_variables)]
pub fn run(
self,
config: Arc<Config>,
package_info: &PackageInfo,
) -> crate::Result<InvokeResponse> {
#[cfg(path_all)]
return match self {
Cmd::ResolvePath { directory, path } => {
resolve_path_handler(&config, package_info, path, directory).map(Into::into)
}
Cmd::Resolve { paths } => resolve(paths).map(Into::into),
Cmd::Normalize { path } => normalize(path).map(Into::into),
Cmd::Join { paths } => join(paths).map(Into::into),
Cmd::Dirname { path } => dirname(path).map(Into::into),
Cmd::Extname { path } => extname(path).map(Into::into),
Cmd::Basename { path, ext } => basename(path, ext).map(Into::into),
Cmd::IsAbsolute { path } => Ok(Path::new(&path).is_absolute()).map(Into::into),
};
#[cfg(not(path_all))]
Err(crate::Error::ApiNotAllowlisted("path".into()))
}
}

#[cfg(path_all)]
pub fn resolve_path_handler(
config: &Config,
package_info: &PackageInfo,
path: String,
directory: Option<BaseDirectory>,
) -> crate::Result<PathBuf> {
crate::api::path::resolve_path(config, package_info, path, directory).map_err(Into::into)
}

#[cfg(path_all)]
fn resolve(paths: Vec<String>) -> crate::Result<String> {
// start with the current directory
let mut resolved_path = PathBuf::new().join(".");

for path in paths {
let path_buf = PathBuf::from(path);

// if we encounter an absolute path, we use it as the starting path for next iteration
if path_buf.is_absolute() {
resolved_path = path_buf;
} else {
resolved_path = resolved_path.join(&path_buf);
}
}

normalize(resolved_path.to_string_lossy().to_string())
}

#[cfg(path_all)]
fn normalize(path: String) -> crate::Result<String> {
let path = std::fs::canonicalize(path)?;
let path = path.to_string_lossy().to_string();

// remove `\\\\?\\` on windows, UNC path
#[cfg(target_os = "windows")]
let path = path.replace("\\\\?\\", "");

Ok(path)
}

#[cfg(path_all)]
fn join(paths: Vec<String>) -> crate::Result<String> {
let mut joined_path = PathBuf::new();
for path in paths {
joined_path = joined_path.join(path);
}
normalize(joined_path.to_string_lossy().to_string())
}

#[cfg(path_all)]
fn dirname(path: String) -> crate::Result<String> {
match Path::new(&path).parent() {
Some(path) => Ok(path.to_string_lossy().to_string()),
None => Err(crate::Error::FailedToExecuteApi(crate::api::Error::Path(
"Couldn't get the parent directory".into(),
))),
}
}

#[cfg(path_all)]
fn extname(path: String) -> crate::Result<String> {
match Path::new(&path)
.extension()
.and_then(std::ffi::OsStr::to_str)
{
Some(path) => Ok(path.to_string()),
None => Err(crate::Error::FailedToExecuteApi(crate::api::Error::Path(
"Couldn't get the extension of the file".into(),
))),
}
}

#[cfg(path_all)]
fn basename(path: String, ext: Option<String>) -> crate::Result<String> {
match Path::new(&path)
.file_name()
.and_then(std::ffi::OsStr::to_str)
{
Some(path) => Ok(if let Some(ext) = ext {
path.replace(ext.as_str(), "")
} else {
path.to_string()
}),
None => Err(crate::Error::FailedToExecuteApi(crate::api::Error::Path(
"Couldn't get the basename".into(),
))),
}
}
1 change: 1 addition & 0 deletions tooling/api/src/helpers/tauri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { invoke } from '../tauri'
type TauriModule =
| 'App'
| 'Fs'
| 'Path'
| 'Os'
| 'Window'
| 'Shell'
Expand Down