chore: update documentation

This commit is contained in:
Lucas Nogueira
2026-09-22 11:30:47 -03:00
parent d869c162a7
commit a87a3c7d44
104 changed files with 4875 additions and 222 deletions
+6
View File
@@ -9,6 +9,12 @@ use crate::{models::*, FilePath, OpenOptions};
const PLUGIN_IDENTIFIER: &str = "com.plugin.fs";
/// Access to the file system APIs on Android.
///
/// In addition to regular file system paths, it can read `content://` URIs
/// and Android asset paths by resolving them with the Android plugin implementation.
///
/// Retrieved with [`crate::FsExt::fs`].
pub struct Fs<R: Runtime>(tauri::plugin::PluginHandle<R>);
pub fn init<R: Runtime, C: DeserializeOwned>(
+3
View File
@@ -8,6 +8,9 @@ use tauri::{AppHandle, Runtime};
use crate::{FilePath, OpenOptions};
/// Access to the file system APIs on desktop.
///
/// Retrieved with [`crate::FsExt::fs`].
pub struct Fs<R: Runtime>(pub(crate) AppHandle<R>);
fn path_or_err<P: Into<FilePath>>(p: P) -> std::io::Result<PathBuf> {
+8
View File
@@ -6,15 +6,20 @@ use std::path::PathBuf;
use serde::{Serialize, Serializer};
/// Errors that can happen while using the file system plugin.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
/// JSON serialization or deserialization error.
#[error(transparent)]
Json(#[from] serde_json::Error),
/// Error from the Tauri APIs, usually raised while resolving a path or a scope entry.
#[error(transparent)]
Tauri(#[from] tauri::Error),
/// Error from the underlying file system operation.
#[error(transparent)]
Io(#[from] std::io::Error),
/// The path is denied by the plugin scope or is not allowed by it.
#[error("forbidden path: {0}")]
PathForbidden(PathBuf),
/// Invalid glob pattern.
@@ -24,11 +29,14 @@ pub enum Error {
#[cfg(feature = "watch")]
#[error(transparent)]
Watch(#[from] notify::Error),
/// Error invoking the Android plugin implementation.
#[cfg(target_os = "android")]
#[error(transparent)]
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
/// The URL cannot be converted to a file system path.
#[error("URL is not a valid path")]
InvalidPathUrl,
/// The path is not safe to use, for instance because it traverses parent directories.
#[error("Unsafe PathBuf: {0}")]
UnsafePathBuf(&'static str),
}
+5
View File
@@ -7,6 +7,11 @@ use tauri::{plugin::PluginApi, AppHandle, Runtime};
use crate::{FilePath, OpenOptions};
/// Access to the file system APIs on iOS.
///
/// Opening a `file://` URL automatically starts accessing the matching security-scoped resource.
///
/// Retrieved with [`crate::FsExt::fs`].
pub struct Fs<R: Runtime> {
_phantom: std::marker::PhantomData<fn() -> R>,
}
+62 -8
View File
@@ -58,6 +58,13 @@ pub use file_path::SafeFilePath;
type Result<T> = std::result::Result<T, Error>;
/// Options and flags which can be used to configure how a file is opened.
///
/// This builder exposes the ability to configure how a [`std::fs::File`] is opened and
/// what operations are permitted on the open file. Build it with [`OpenOptions::new`],
/// chain calls to the setter methods and pass it to [`Fs::open`].
///
/// The `read` option defaults to `true`, every other option defaults to `false`.
#[derive(Debug, Default, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OpenOptions {
@@ -199,12 +206,14 @@ impl OpenOptions {
/// This function doesn't create the file if it doesn't exist. Use the
/// [`OpenOptions::create`] method to do so.
///
/// [`write()`]: Write::write "io::Write::write"
/// [`flush()`]: Write::flush "io::Write::flush"
/// [stream_position]: Seek::stream_position "io::Seek::stream_position"
/// [seek]: Seek::seek "io::Seek::seek"
/// [Current]: SeekFrom::Current "io::SeekFrom::Current"
/// [End]: SeekFrom::End "io::SeekFrom::End"
/// [`write()`]: std::io::Write::write "io::Write::write"
/// [`flush()`]: std::io::Write::flush "io::Write::flush"
/// [Seek]: std::io::Seek "io::Seek"
/// [stream_position]: std::io::Seek::stream_position "io::Seek::stream_position"
/// [seek]: std::io::Seek::seek "io::Seek::seek"
/// [SeekFrom]: std::io::SeekFrom "io::SeekFrom"
/// [Current]: std::io::SeekFrom::Current "io::SeekFrom::Current"
/// [End]: std::io::SeekFrom::End "io::SeekFrom::End"
///
/// # Examples
///
@@ -260,7 +269,7 @@ impl OpenOptions {
/// No file is allowed to exist at the target location, also no (dangling) symlink. In this
/// way, if the call succeeds, the file returned is guaranteed to be new.
/// If a file exists at the target location, creating a new file will fail with [`AlreadyExists`]
/// or another error based on the situation. See [`OpenOptions::open`] for a
/// or another error based on the situation. See [`std::fs::OpenOptions::open`] for a
/// non-exhaustive list of likely errors.
///
/// This option is useful because it is atomic. Otherwise between checking
@@ -275,7 +284,7 @@ impl OpenOptions {
///
/// [`.create()`]: OpenOptions::create
/// [`.truncate()`]: OpenOptions::truncate
/// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
/// [`AlreadyExists`]: std::io::ErrorKind::AlreadyExists
///
/// # Examples
///
@@ -328,6 +337,14 @@ impl OpenOptions {
}
impl<R: Runtime> Fs<R> {
/// Reads the entire contents of a file into a string.
///
/// The file is opened in read-only mode with [`Fs::open`].
///
/// # Errors
///
/// Returns an error if `path` cannot be opened for reading or if its
/// contents are not valid UTF-8.
pub fn read_to_string<P: Into<FilePath>>(&self, path: P) -> std::io::Result<String> {
let mut s = String::new();
self.open(
@@ -341,6 +358,13 @@ impl<R: Runtime> Fs<R> {
Ok(s)
}
/// Reads the entire contents of a file into a bytes vector.
///
/// The file is opened in read-only mode with [`Fs::open`].
///
/// # Errors
///
/// Returns an error if `path` cannot be opened for reading.
pub fn read<P: Into<FilePath>>(&self, path: P) -> std::io::Result<Vec<u8>> {
let mut buf = Vec::new();
self.open(
@@ -432,8 +456,37 @@ impl SecurityScopedResources {
pub(crate) fn remove(&self, _url: &str) {}
}
/// Extension trait implemented by every [`Manager`] (the app handle, windows, webviews, ...)
/// to access the file system plugin APIs.
///
/// # Examples
///
/// ```rust,no_run
/// use std::path::Path;
/// use tauri::Runtime;
/// use tauri_plugin_fs::FsExt;
///
/// fn setup<R: Runtime>(app: &tauri::App<R>) -> Result<(), Box<dyn std::error::Error>> {
/// // allow the app to access a directory that is not part of the static scope
/// app.fs_scope().allow_directory(Path::new("/path/to/directory"), true)?;
///
/// let contents = app.fs().read_to_string(Path::new("/path/to/directory/file.txt"))?;
/// println!("{contents}");
///
/// Ok(())
/// }
/// ```
pub trait FsExt<R: Runtime> {
/// Returns the file system scope, which can be used to dynamically
/// allow or deny paths at runtime.
///
/// # Panics
///
/// Panics if the plugin is not registered in the app.
/// Use [`FsExt::try_fs_scope`] if the plugin might not be registered.
fn fs_scope(&self) -> tauri::fs::Scope;
/// Returns the file system scope, or `None` if the plugin is not registered in the app.
fn try_fs_scope(&self) -> Option<tauri::fs::Scope>;
/// Cross platform file system APIs that also support manipulating Android files.
@@ -454,6 +507,7 @@ impl<R: Runtime, T: Manager<R>> FsExt<R> for T {
}
}
/// Initializes the plugin.
pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
PluginBuilder::<R, Option<config::Config>>::new("fs")
.invoke_handler(tauri::generate_handler![