mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-09-22 21:30:44 +02:00
chore: update documentation
This commit is contained in:
+172
-16
@@ -88,9 +88,15 @@
|
||||
import { BaseDirectory } from '@tauri-apps/api/path'
|
||||
import { Channel, invoke, Resource } from '@tauri-apps/api/core'
|
||||
|
||||
/**
|
||||
* Defines how the offset given to {@linkcode FileHandle.seek} is interpreted.
|
||||
*/
|
||||
enum SeekMode {
|
||||
/** The offset is relative to the start of the file. */
|
||||
Start = 0,
|
||||
/** The offset is relative to the current cursor position. */
|
||||
Current = 1,
|
||||
/** The offset is relative to the end of the file. */
|
||||
End = 2
|
||||
}
|
||||
|
||||
@@ -322,6 +328,8 @@ class FileHandle extends Resource {
|
||||
* await file.close();
|
||||
* ```
|
||||
*
|
||||
* @param buffer The buffer the file contents are read into.
|
||||
* @returns A promise resolving to the number of bytes read, or `null` when the end of the file was reached.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async read(buffer: Uint8Array): Promise<number | null> {
|
||||
@@ -377,6 +385,9 @@ class FileHandle extends Resource {
|
||||
* await file.close();
|
||||
* ```
|
||||
*
|
||||
* @param offset The number of bytes the cursor is moved by.
|
||||
* @param whence Defines the position the `offset` is relative to.
|
||||
* @returns A promise resolving to the new cursor position, relative to the start of the file.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async seek(offset: number, whence: SeekMode): Promise<number> {
|
||||
@@ -399,6 +410,7 @@ class FileHandle extends Resource {
|
||||
* await file.close();
|
||||
* ```
|
||||
*
|
||||
* @returns A promise resolving to the metadata of this file.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async stat(): Promise<FileInfo> {
|
||||
@@ -431,6 +443,7 @@ class FileHandle extends Resource {
|
||||
* await file.close();
|
||||
* ```
|
||||
*
|
||||
* @param len The length the file is truncated or extended to, in bytes. When not provided the entire file contents are truncated.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async truncate(len?: number): Promise<void> {
|
||||
@@ -458,6 +471,8 @@ class FileHandle extends Resource {
|
||||
* await file.close();
|
||||
* ```
|
||||
*
|
||||
* @param data The bytes written to the file.
|
||||
* @returns A promise resolving to the number of bytes written.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async write(data: Uint8Array): Promise<number> {
|
||||
@@ -469,6 +484,8 @@ class FileHandle extends Resource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `create` function, which creates or truncates a file.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface CreateOptions {
|
||||
@@ -488,6 +505,9 @@ interface CreateOptions {
|
||||
* await file.close();
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file, relative to `options.baseDir` when it is provided.
|
||||
* @param options Options defining the base directory of `path`.
|
||||
* @returns A promise resolving to the handle of the created file.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function create(
|
||||
@@ -507,6 +527,8 @@ async function create(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `open` function, defining how the file is opened and which operations are allowed on it.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface OpenOptions {
|
||||
@@ -573,6 +595,9 @@ interface OpenOptions {
|
||||
* await file.close();
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file, relative to `options.baseDir` when it is provided.
|
||||
* @param options Options defining the base directory of `path` and how the file is opened.
|
||||
* @returns A promise resolving to the handle of the open file.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function open(
|
||||
@@ -592,6 +617,8 @@ async function open(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `copyFile` function, defining the base directory of each path.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface CopyFileOptions {
|
||||
@@ -609,6 +636,9 @@ interface CopyFileOptions {
|
||||
* await copyFile('app.conf', 'app.conf.bk', { fromPathBaseDir: BaseDirectory.AppConfig, toPathBaseDir: BaseDirectory.AppConfig });
|
||||
* ```
|
||||
*
|
||||
* @param fromPath The path of the file to copy from.
|
||||
* @param toPath The path of the file to copy to.
|
||||
* @param options Options defining the base directory of each path.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function copyFile(
|
||||
@@ -631,6 +661,8 @@ async function copyFile(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `mkdir` function, which creates a directory.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface MkdirOptions {
|
||||
@@ -652,6 +684,8 @@ interface MkdirOptions {
|
||||
* await mkdir('users', { baseDir: BaseDirectory.AppLocalData });
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the directory to create.
|
||||
* @param options Options defining the base directory of `path`, the directory permissions and whether intermediate directories are created.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function mkdir(
|
||||
@@ -669,6 +703,8 @@ async function mkdir(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `readDir` function, which lists the entries of a directory.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface ReadDirOptions {
|
||||
@@ -700,20 +736,23 @@ interface DirEntry {
|
||||
* ```typescript
|
||||
* import { readDir, BaseDirectory } from '@tauri-apps/plugin-fs';
|
||||
* import { join } from '@tauri-apps/api/path';
|
||||
* const dir = "users"
|
||||
* const entries = await readDir('users', { baseDir: BaseDirectory.AppLocalData });
|
||||
* processEntriesRecursively(dir, entries);
|
||||
* const dir = 'users';
|
||||
* const entries = await readDir(dir, { baseDir: BaseDirectory.AppLocalData });
|
||||
* await processEntriesRecursively(dir, entries);
|
||||
* async function processEntriesRecursively(parent, entries) {
|
||||
* for (const entry of entries) {
|
||||
* console.log(`Entry: ${entry.name}`);
|
||||
* if (entry.isDirectory) {
|
||||
* const dir = await join(parent, entry.name);
|
||||
* processEntriesRecursively(dir, await readDir(dir, { baseDir: BaseDirectory.AppLocalData }))
|
||||
* const entryPath = await join(parent, entry.name);
|
||||
* await processEntriesRecursively(entryPath, await readDir(entryPath, { baseDir: BaseDirectory.AppLocalData }));
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the directory to read.
|
||||
* @param options Options defining the base directory of `path`.
|
||||
* @returns A promise resolving to the list of entries in the directory.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function readDir(
|
||||
@@ -731,6 +770,8 @@ async function readDir(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the functions that read a file, such as `readFile` and `readTextFile`.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface ReadFileOptions {
|
||||
@@ -749,6 +790,9 @@ interface ReadFileOptions {
|
||||
* const contents = await readFile('avatar.png', { baseDir: BaseDirectory.Resource });
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file to read.
|
||||
* @param options Options defining the base directory of `path`.
|
||||
* @returns A promise resolving to the contents of the file as bytes.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function readFile(
|
||||
@@ -775,6 +819,9 @@ async function readFile(
|
||||
* const contents = await readTextFile('app.conf', { baseDir: BaseDirectory.AppConfig });
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file to read.
|
||||
* @param options Options defining the base directory of `path` and the text encoding.
|
||||
* @returns A promise resolving to the contents of the file as a string.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function readTextFile(
|
||||
@@ -808,6 +855,9 @@ async function readTextFile(
|
||||
* You could also call {@linkcode AsyncIterableIterator.next} to advance the
|
||||
* iterator so you can lazily read the next line whenever you want.
|
||||
*
|
||||
* @param path The path of the file to read.
|
||||
* @param options Options defining the base directory of `path` and the text encoding.
|
||||
* @returns A promise resolving to an iterator over the lines of the file.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function readTextFileLines(
|
||||
@@ -873,6 +923,8 @@ async function readTextFileLines(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `remove` function, which deletes a file or a directory.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface RemoveOptions {
|
||||
@@ -892,6 +944,8 @@ interface RemoveOptions {
|
||||
* await remove('users', { baseDir: BaseDirectory.AppLocalData });
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file or directory to remove.
|
||||
* @param options Options defining the base directory of `path` and whether directories are removed recursively.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function remove(
|
||||
@@ -909,6 +963,8 @@ async function remove(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `rename` function, defining the base directory of each path.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface RenameOptions {
|
||||
@@ -931,6 +987,9 @@ interface RenameOptions {
|
||||
* await rename('avatar.png', 'deleted.png', { oldPathBaseDir: BaseDirectory.App, newPathBaseDir: BaseDirectory.AppLocalData });
|
||||
* ```
|
||||
*
|
||||
* @param oldPath The path of the file or directory to rename.
|
||||
* @param newPath The path the file or directory is renamed to.
|
||||
* @param options Options defining the base directory of each path.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function rename(
|
||||
@@ -953,6 +1012,8 @@ async function rename(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `stat` and `lstat` functions, which read the metadata of a path.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface StatOptions {
|
||||
@@ -971,6 +1032,9 @@ interface StatOptions {
|
||||
* console.log(fileInfo.isFile); // true
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file or directory to inspect.
|
||||
* @param options Options defining the base directory of `path`.
|
||||
* @returns A promise resolving to the metadata of the file or directory.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function stat(
|
||||
@@ -997,6 +1061,9 @@ async function stat(
|
||||
* console.log(fileInfo.isFile); // true
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file, directory or symlink to inspect.
|
||||
* @param options Options defining the base directory of `path`.
|
||||
* @returns A promise resolving to the metadata of the path itself.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function lstat(
|
||||
@@ -1012,6 +1079,8 @@ async function lstat(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `truncate` function, which truncates or extends a file.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface TruncateOptions {
|
||||
@@ -1037,6 +1106,9 @@ interface TruncateOptions {
|
||||
* console.log(data); // "Hello W"
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file to truncate or extend.
|
||||
* @param len The length the file is resized to, in bytes. Defaults to `0`.
|
||||
* @param options Options defining the base directory of `path`.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function truncate(
|
||||
@@ -1056,6 +1128,8 @@ async function truncate(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `writeFile` and `writeTextFile` functions, defining how the file is opened before writing to it.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface WriteFileOptions {
|
||||
@@ -1082,6 +1156,9 @@ interface WriteFileOptions {
|
||||
* await writeFile('file.txt', data, { baseDir: BaseDirectory.AppLocalData });
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file to write to.
|
||||
* @param data The bytes written to the file, either as a buffer or as a stream of chunks.
|
||||
* @param options Options defining the base directory of `path` and how the file is opened.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function writeFile(
|
||||
@@ -1123,16 +1200,20 @@ async function writeFile(
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes UTF-8 string `data` to the given `path`, by default creating a new file if needed, else overwriting.
|
||||
@example
|
||||
* ```typescript
|
||||
* import { writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';
|
||||
*
|
||||
* await writeTextFile('file.txt', "Hello world", { baseDir: BaseDirectory.AppLocalData });
|
||||
* ```
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
* Writes UTF-8 string `data` to the given `path`, by default creating a new file if needed, else overwriting.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';
|
||||
*
|
||||
* await writeTextFile('file.txt', "Hello world", { baseDir: BaseDirectory.AppLocalData });
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file to write to.
|
||||
* @param data The UTF-8 string written to the file.
|
||||
* @param options Options defining the base directory of `path` and how the file is opened.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function writeTextFile(
|
||||
path: string | URL,
|
||||
data: string,
|
||||
@@ -1153,6 +1234,8 @@ async function writeTextFile(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `exists` function, which checks whether a path exists.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface ExistsOptions {
|
||||
@@ -1169,6 +1252,9 @@ interface ExistsOptions {
|
||||
* await exists('avatar.png', { baseDir: BaseDirectory.AppData });
|
||||
* ```
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @param options Options defining the base directory of `path`.
|
||||
* @returns A promise resolving to `true` when the path exists, `false` otherwise.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function exists(
|
||||
@@ -1186,6 +1272,8 @@ async function exists(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `watchImmediate` function, which reports file system changes as they happen.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface WatchOptions {
|
||||
@@ -1196,23 +1284,35 @@ interface WatchOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for the `watch` function, which reports file system changes after a debounce delay.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface DebouncedWatchOptions extends WatchOptions {
|
||||
/** Debounce delay */
|
||||
/**
|
||||
* The debounce delay in milliseconds. Changes that happen within this
|
||||
* window are grouped and reported together. Defaults to `2000`.
|
||||
*/
|
||||
delayMs?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* A file system change reported to the callback of `watch` or `watchImmediate`.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
interface WatchEvent {
|
||||
/** The kind of change that was detected. */
|
||||
type: WatchEventKind
|
||||
/** The paths affected by the change. */
|
||||
paths: string[]
|
||||
/** Additional attributes reported by the underlying file system watcher. */
|
||||
attrs: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* The kind of file system change described by a `WatchEvent`.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
type WatchEventKind =
|
||||
@@ -1224,6 +1324,8 @@ type WatchEventKind =
|
||||
| 'other'
|
||||
|
||||
/**
|
||||
* Describes how a file or directory was accessed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
type WatchEventKindAccess =
|
||||
@@ -1233,6 +1335,8 @@ type WatchEventKindAccess =
|
||||
| { kind: 'other' }
|
||||
|
||||
/**
|
||||
* Describes which kind of entry was created.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
type WatchEventKindCreate =
|
||||
@@ -1242,6 +1346,8 @@ type WatchEventKindCreate =
|
||||
| { kind: 'other' }
|
||||
|
||||
/**
|
||||
* Describes what was modified on a file or directory.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
type WatchEventKindModify =
|
||||
@@ -1262,6 +1368,8 @@ type WatchEventKindModify =
|
||||
| { kind: 'other' }
|
||||
|
||||
/**
|
||||
* Describes which kind of entry was removed.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
type WatchEventKindRemove =
|
||||
@@ -1272,6 +1380,8 @@ type WatchEventKindRemove =
|
||||
|
||||
// TODO: Remove this in v3, return `Watcher` instead
|
||||
/**
|
||||
* Stops watching the paths it was created for. Returned by `watch` and `watchImmediate`.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
type UnwatchFn = () => void
|
||||
@@ -1311,6 +1421,27 @@ async function watchInternal(
|
||||
/**
|
||||
* Watch changes (after a delay) on files or directories.
|
||||
*
|
||||
* Events that happen within the `delayMs` window are grouped and delivered in a single callback call.
|
||||
* Requires the `watch` Cargo feature of the Rust plugin to be enabled.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { watch, BaseDirectory } from '@tauri-apps/plugin-fs';
|
||||
*
|
||||
* const unwatch = await watch(
|
||||
* 'app.conf',
|
||||
* (event) => console.log(event.type, event.paths),
|
||||
* { baseDir: BaseDirectory.AppConfig, delayMs: 500 }
|
||||
* );
|
||||
*
|
||||
* // stop watching when you are done
|
||||
* unwatch();
|
||||
* ```
|
||||
*
|
||||
* @param paths The path or list of paths to watch. Each path can be a string or a `file://` URL.
|
||||
* @param cb The callback executed for each batch of file system changes.
|
||||
* @param options Options defining the base directory of the paths, the debounce delay and whether directories are watched recursively.
|
||||
* @returns A promise resolving to a function that stops watching the given paths.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function watch(
|
||||
@@ -1328,6 +1459,27 @@ async function watch(
|
||||
/**
|
||||
* Watch changes on files or directories.
|
||||
*
|
||||
* Unlike `watch`, changes are reported as soon as they are detected, without a debounce delay.
|
||||
* Requires the `watch` Cargo feature of the Rust plugin to be enabled.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { watchImmediate, BaseDirectory } from '@tauri-apps/plugin-fs';
|
||||
*
|
||||
* const unwatch = await watchImmediate(
|
||||
* 'logs',
|
||||
* (event) => console.log(event.type, event.paths),
|
||||
* { baseDir: BaseDirectory.AppLog, recursive: true }
|
||||
* );
|
||||
*
|
||||
* // stop watching when you are done
|
||||
* unwatch();
|
||||
* ```
|
||||
*
|
||||
* @param paths The path or list of paths to watch. Each path can be a string or a `file://` URL.
|
||||
* @param cb The callback executed for each file system change.
|
||||
* @param options Options defining the base directory of the paths and whether directories are watched recursively.
|
||||
* @returns A promise resolving to a function that stops watching the given paths.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function watchImmediate(
|
||||
@@ -1354,6 +1506,8 @@ async function watchImmediate(
|
||||
* console.log(dirSize); // 1024
|
||||
* ```
|
||||
*
|
||||
* @param path The path of the file or directory to measure.
|
||||
* @returns A promise resolving to the size in bytes.
|
||||
* @since 2.1.0
|
||||
*/
|
||||
async function size(path: string | URL): Promise<number> {
|
||||
@@ -1390,6 +1544,7 @@ async function size(path: string | URL): Promise<number> {
|
||||
* // ... use the resource ...
|
||||
* ```
|
||||
*
|
||||
* @param path The path or `file://` URL of the resource to start accessing.
|
||||
* @since 2.5.0
|
||||
*/
|
||||
async function startAccessingSecurityScopedResource(
|
||||
@@ -1425,6 +1580,7 @@ async function startAccessingSecurityScopedResource(
|
||||
* await stopAccessingSecurityScopedResource(filePath);
|
||||
* ```
|
||||
*
|
||||
* @param path The path or `file://` URL of the resource to stop accessing.
|
||||
* @since 2.5.0
|
||||
*/
|
||||
async function stopAccessingSecurityScopedResource(
|
||||
|
||||
@@ -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>(
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
@@ -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
@@ -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![
|
||||
|
||||
Reference in New Issue
Block a user