feat(tauri) extend file system API (#512)

* feat(tauri) extend file system API

* chore(deps) pin web-view deps
This commit is contained in:
Lucas Fernandes Nogueira
2020-03-16 17:04:15 -03:00
committed by GitHub
parent 37e8e79a04
commit 8ac066700a
9 changed files with 502 additions and 12 deletions

View File

@@ -51,9 +51,71 @@ function readDir (dir, options = {}) {
return tauri.readDir(dir, options)
}
/**
* Creates a directory
* If one of the path's parent components doesn't exist and the `recursive` option isn't set to true, it will be rejected
*
* @param {string} dir path to the directory to create
* @param {object} [options] configuration object
* @param {boolean} [options.recursive] whether to create the directory's parent components or not
* @return {Promise<void>}
*/
function createDir (dir, options = {}) {
return tauri.createDir(dir, options)
}
/**
* Removes a directory
* If the directory is not empty and the `recursive` option isn't set to true, it will be rejected
*
* @param {string} dir path to the directory to remove
* @param {object} [options] configuration object
* @param {boolean} [options.recursive] whether to remove all of the directory's content or not
* @return {Promise<void>}
*/
function removeDir (dir, options = {}) {
return tauri.removeDir(dir, options)
}
/**
* Copy file
*
* @param {string} source
* @param {string} destination
* @return {Promise<void>}
*/
function copyFile (source, destination) {
return tauri.copyFile(source, destination)
}
/**
* Removes a file
*
* @param {string} file path to the file to remove
* @return {Promise<void>}
*/
function removeFile (file) {
return tauri.removeFile(file)
}
/**
* Renames a file
*
* @param {string} oldPath
* @param {string} newPath
* @return {Promise<void>}
*/
function renameFile (oldPath, newPath) {
return tauri.renameFile(oldPath, newPath)
}
export {
readTextFile,
readBinaryFile,
writeFile,
readDir
readDir,
createDir,
removeDir,
copyFile,
removeFile
}

View File

@@ -306,6 +306,130 @@ window.tauri = {
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name createDir
* @description Creates a directory
* Permissions based on the app's PID owner
* @param {String} path
* @param {Object} [options]
* @param {Boolean} [options.recursive]
* @returns {*|Promise<any>|Promise}
*/
<% } %>
createDir: function createDir(path, options) {
<% if (tauri.whitelist.createDir === true || tauri.whitelist.all === true) { %>
return this.promisified({
cmd: 'createDir',
path: path,
options: options
});
<% } else { %>
<% if (ctx.dev) { %>
return __whitelistWarning('createDir')
<% } %>
return __reject()
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name removeDir
* @description Removes a directory
* Permissions based on the app's PID owner
* @param {String} path
* @param {Object} [options]
* @param {Boolean} [options.recursive]
* @returns {*|Promise<any>|Promise}
*/
<% } %>
removeDir: function removeDir(path, options) {
<% if (tauri.whitelist.removeDir === true || tauri.whitelist.all === true) { %>
return this.promisified({
cmd: 'removeDir',
path: path,
options: options
});
<% } else { %>
<% if (ctx.dev) { %>
return __whitelistWarning('removeDir')
<% } %>
return __reject()
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name copyFile
* @description Copy file
* Permissions based on the app's PID owner
* @param {String} source
* @param {String} destination
* @returns {*|Promise<any>|Promise}
*/
<% } %>
copyFile: function copyFile(source, destination) {
<% if (tauri.whitelist.copyFile === true || tauri.whitelist.all === true) { %>
return this.promisified({
cmd: 'copyFile',
source: source,
destination: destination
});
<% } else { %>
<% if (ctx.dev) { %>
return __whitelistWarning('copyFile')
<% } %>
return __reject()
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name removeFile
* @description Removes a file
* Permissions based on the app's PID owner
* @param {String} path
* @returns {*|Promise<any>|Promise}
*/
<% } %>
removeFile: function removeFile(path) {
<% if (tauri.whitelist.removeFile === true || tauri.whitelist.all === true) { %>
return this.promisified({
cmd: 'removeFile',
path: path
});
<% } else { %>
<% if (ctx.dev) { %>
return __whitelistWarning('removeFile')
<% } %>
return __reject()
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name renameFile
* @description Renames a file
* Permissions based on the app's PID owner
* @param {String} path
* @returns {*|Promise<any>|Promise}
*/
<% } %>
renameFile: function renameFile(oldPath, newPath) {
<% if (tauri.whitelist.renameFile === true || tauri.whitelist.all === true) { %>
return this.promisified({
cmd: 'renameFile',
old_path: oldPath,
new_path: newPath
});
<% } else { %>
<% if (ctx.dev) { %>
return __whitelistWarning('renameFile')
<% } %>
return __reject()
<% } %>
},
<% if (ctx.dev) { %>
/**
* @name setTitle

View File

@@ -44,7 +44,7 @@ pub fn walk_dir(path_copy: String) -> crate::Result<Vec<DiskEntry>> {
pub fn list_dir_contents(dir_path: String) -> crate::Result<Vec<DiskEntry>> {
fs::read_dir(dir_path)
.map_err(|err| crate::Error::with_chain(err, "read string failed"))
.map_err(|err| crate::Error::with_chain(err, "read dir failed"))
.and_then(|paths| {
let mut dirs: Vec<DiskEntry> = vec![];
for path in paths {

View File

@@ -12,7 +12,8 @@ exclude = ["test/fixture/**"]
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
web-view = "0.6.0"
webview-sys = "=0.4.0"
web-view = "=0.6.0"
tauri_includedir = "0.5.0"
phf = "0.8.0"
base64 = "0.12.0"
@@ -44,6 +45,11 @@ read-text-file = []
read-binary-file = []
write-file = []
read-dir = []
copy-file = []
create-dir = []
remove-dir = []
remove-file = []
rename-file = []
set-title = []
execute = []
open = []

View File

@@ -277,6 +277,105 @@ window.tauri = {
},
/**
* @name createDir
* @description Creates a directory
* Permissions based on the app's PID owner
* @param {String} path
* @param {Object} [options]
* @param {Boolean} [options.recursive]
* @returns {*|Promise<any>|Promise}
*/
createDir: function createDir(path, options) {
return this.promisified({
cmd: 'createDir',
path: path,
options: options
});
},
/**
* @name removeDir
* @description Removes a directory
* Permissions based on the app's PID owner
* @param {String} path
* @param {Object} [options]
* @param {Boolean} [options.recursive]
* @returns {*|Promise<any>|Promise}
*/
removeDir: function removeDir(path, options) {
return this.promisified({
cmd: 'removeDir',
path: path,
options: options
});
},
/**
* @name copyFile
* @description Copy file
* Permissions based on the app's PID owner
* @param {String} source
* @param {String} destination
* @returns {*|Promise<any>|Promise}
*/
copyFile: function copyFile(source, destination) {
return this.promisified({
cmd: 'copyFile',
source: source,
destination: destination
});
},
/**
* @name removeFile
* @description Removes a file
* Permissions based on the app's PID owner
* @param {String} path
* @returns {*|Promise<any>|Promise}
*/
removeFile: function removeFile(path) {
return this.promisified({
cmd: 'removeFile',
path: path
});
},
/**
* @name renameFile
* @description Renames a file
* Permissions based on the app's PID owner
* @param {String} path
* @returns {*|Promise<any>|Promise}
*/
renameFile: function renameFile(oldPath, newPath) {
return this.promisified({
cmd: 'renameFile',
old_path: oldPath,
new_path: newPath
});
},
/**
* @name setTitle
* @description Set the application's title

View File

@@ -58,6 +58,50 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> cra
} => {
file_system::read_dir(webview, path, options, callback, error);
}
#[cfg(any(feature = "all-api", feature = "copy-file"))]
CopyFile {
source,
destination,
callback,
error,
} => {
file_system::copy_file(webview, source, destination, callback, error);
}
#[cfg(any(feature = "all-api", feature = "create-dir"))]
CreateDir {
path,
options,
callback,
error,
} => {
file_system::create_dir(webview, path, options, callback, error);
}
#[cfg(any(feature = "all-api", feature = "remove-dir"))]
RemoveDir {
path,
options,
callback,
error,
} => {
file_system::remove_dir(webview, path, options, callback, error);
}
#[cfg(any(feature = "all-api", feature = "remove-file"))]
RemoveFile {
path,
callback,
error,
} => {
file_system::remove_file(webview, path, callback, error);
}
#[cfg(any(feature = "all-api", feature = "rename-file"))]
RenameFile {
old_path,
new_path,
callback,
error,
} => {
file_system::rename_file(webview, old_path, new_path, callback, error);
}
#[cfg(any(feature = "all-api", feature = "set-title"))]
SetTitle { title } => {
webview.set_title(&title)?;

View File

@@ -1,7 +1,7 @@
use serde::Deserialize;
#[derive(Deserialize)]
pub struct ReadDirOptions {
pub struct DirOperationOptions {
#[serde(default)]
pub recursive: bool
}
@@ -48,7 +48,41 @@ pub enum Cmd {
#[cfg(any(feature = "all-api", feature = "read-dir"))]
ReadDir {
path: String,
options: Option<ReadDirOptions>,
options: Option<DirOperationOptions>,
callback: String,
error: String,
},
#[cfg(any(feature = "all-api", feature = "copy-file"))]
CopyFile {
source: String,
destination: String,
callback: String,
error: String,
},
#[cfg(any(feature = "all-api", feature = "create-dir"))]
CreateDir {
path: String,
options: Option<DirOperationOptions>,
callback: String,
error: String,
},
#[cfg(any(feature = "all-api", feature = "remove-dir"))]
RemoveDir {
path: String,
options: Option<DirOperationOptions>,
callback: String,
error: String,
},
#[cfg(any(feature = "all-api", feature = "remove-file"))]
RemoveFile {
path: String,
callback: String,
error: String,
},
#[cfg(any(feature = "all-api", feature = "rename-file"))]
RenameFile {
old_path: String,
new_path: String,
callback: String,
error: String,
},

View File

@@ -3,15 +3,16 @@ use web_view::WebView;
use tauri_api::dir;
use tauri_api::file;
use std::fs;
use std::fs::File;
use std::io::Write;
use super::cmd::{ReadDirOptions};
use super::cmd::{DirOperationOptions};
pub fn read_dir<T: 'static>(
webview: &mut WebView<'_, T>,
path: String,
options: Option<ReadDirOptions>,
options: Option<DirOperationOptions>,
callback: String,
error: String,
) {
@@ -25,11 +26,11 @@ pub fn read_dir<T: 'static>(
};
if recursive {
dir::walk_dir(path)
.map_err(|e| crate::ErrorKind::Command(e.to_string()).into())
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.and_then(|f| serde_json::to_string(&f).map_err(|err| err.into()))
} else {
dir::list_dir_contents(path)
.map_err(|e| crate::ErrorKind::Command(e.to_string()).into())
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.and_then(|f| serde_json::to_string(&f).map_err(|err| err.into()))
}
},
@@ -38,6 +39,122 @@ pub fn read_dir<T: 'static>(
);
}
pub fn copy_file<T: 'static>(
webview: &mut WebView<'_, T>,
source: String,
destination: String,
callback: String,
error: String,
) {
crate::execute_promise(
webview,
move || {
fs::copy(source, destination)
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.map(|_| "".to_string())
},
callback,
error,
);
}
pub fn create_dir<T: 'static>(
webview: &mut WebView<'_, T>,
path: String,
options: Option<DirOperationOptions>,
callback: String,
error: String,
) {
crate::execute_promise(
webview,
move || {
let recursive = if let Some(options_value) = options {
options_value.recursive
} else {
false
};
let response = if recursive {
fs::create_dir_all(path)
} else {
fs::create_dir(path)
};
response
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.map(|_| "".to_string())
},
callback,
error,
);
}
pub fn remove_dir<T: 'static>(
webview: &mut WebView<'_, T>,
path: String,
options: Option<DirOperationOptions>,
callback: String,
error: String,
) {
crate::execute_promise(
webview,
move || {
let recursive = if let Some(options_value) = options {
options_value.recursive
} else {
false
};
let response = if recursive {
fs::remove_dir_all(path)
} else {
fs::remove_dir(path)
};
response
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.map(|_| "".to_string())
},
callback,
error,
);
}
pub fn remove_file<T: 'static>(
webview: &mut WebView<'_, T>,
path: String,
callback: String,
error: String,
) {
crate::execute_promise(
webview,
move || {
fs::remove_file(path)
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.map(|_| "".to_string())
},
callback,
error,
);
}
pub fn rename_file<T: 'static>(
webview: &mut WebView<'_, T>,
old_path: String,
new_path: String,
callback: String,
error: String,
) {
crate::execute_promise(
webview,
move || {
fs::rename(old_path, new_path)
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.map(|_| "".to_string())
},
callback,
error,
);
}
pub fn write_file<T: 'static>(
webview: &mut WebView<'_, T>,
file: String,
@@ -49,7 +166,7 @@ pub fn write_file<T: 'static>(
webview,
move || {
File::create(file)
.map_err(|e| crate::ErrorKind::Command(e.to_string()).into())
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.and_then(|mut f| {
f.write_all(contents.as_bytes())
.map_err(|err| err.into())
@@ -71,7 +188,7 @@ pub fn read_text_file<T: 'static>(
webview,
move || {
file::read_string(path)
.map_err(|e| crate::ErrorKind::Command(e.to_string()).into())
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.and_then(|f| {
serde_json::to_string(&f)
.map_err(|err| err.into())
@@ -92,7 +209,7 @@ pub fn read_binary_file<T: 'static>(
webview,
move || {
file::read_binary(path)
.map_err(|e| crate::ErrorKind::Command(e.to_string()).into())
.map_err(|e| crate::ErrorKind::FileSystem(e.to_string()).into())
.and_then(|f| {
serde_json::to_string(&f)
.map_err(|err| err.into())

View File

@@ -42,6 +42,10 @@ error_chain! {
description("Command Error")
display("Command Error: '{}'", t)
}
FileSystem(t: String) {
description("FileSystem Error")
display("FileSystem Error: '{}'", t)
}
Dialog(t: String) {
description("Dialog Error")
display("Dialog Error: '{}'", t)