Skip to content

Commit

Permalink
Merge branch 'v2' into feat/fs/performance
Browse files Browse the repository at this point in the history
  • Loading branch information
amrbashir committed Nov 21, 2024
2 parents 1511204 + 5092ea5 commit 84950ec
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 42 deletions.
7 changes: 7 additions & 0 deletions .changes/fs-readable-stream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"fs": "patch"
"fs-js": "patch"
---

Add support for using `ReadableStream<Unit8Array>` with `writeFile` API.

2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions plugins/fs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ ios = { level = "partial", notes = "Access is restricted to Application folder b
tauri-plugin = { workspace = true, features = ["build"] }
schemars = { workspace = true }
serde = { workspace = true }
toml = "0.8"
tauri-utils = { workspace = true, features = ["build"] }

[dependencies]
serde = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion plugins/fs/api-iife.js

Large diffs are not rendered by default.

92 changes: 66 additions & 26 deletions plugins/fs/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use std::{
path::{Path, PathBuf},
};

use tauri_utils::acl::manifest::PermissionFile;

#[path = "src/scope.rs"]
#[allow(dead_code)]
mod scope;
Expand Down Expand Up @@ -75,31 +77,31 @@ const BASE_DIR_VARS: &[&str] = &[
"APPCACHE",
"APPLOG",
];
const COMMANDS: &[&str] = &[
"mkdir",
"create",
"copy_file",
"remove",
"rename",
"truncate",
"ftruncate",
"write",
"write_file",
"write_text_file",
"read_dir",
"read_file",
"read",
"open",
"read_text_file",
"read_text_file_lines",
"read_text_file_lines_next",
"seek",
"stat",
"lstat",
"fstat",
"exists",
"watch",
"unwatch",
const COMMANDS: &[(&str, &[&str])] = &[
("mkdir", &[]),
("create", &[]),
("copy_file", &[]),
("remove", &[]),
("rename", &[]),
("truncate", &[]),
("ftruncate", &[]),
("write", &[]),
("write_file", &["open", "write"]),
("write_text_file", &[]),
("read_dir", &[]),
("read_file", &[]),
("read", &[]),
("open", &[]),
("read_text_file", &[]),
("read_text_file_lines", &["read_text_file_lines_next"]),
("read_text_file_lines_next", &[]),
("seek", &[]),
("stat", &[]),
("lstat", &[]),
("fstat", &[]),
("exists", &[]),
("watch", &[]),
("unwatch", &[]),
];

fn main() {
Expand Down Expand Up @@ -205,9 +207,47 @@ permissions = [
}
}

tauri_plugin::Builder::new(COMMANDS)
tauri_plugin::Builder::new(&COMMANDS.iter().map(|c| c.0).collect::<Vec<_>>())
.global_api_script_path("./api-iife.js")
.global_scope_schema(schemars::schema_for!(FsScopeEntry))
.android_path("android")
.build();

// workaround to include nested permissions as `tauri_plugin` doesn't support it
let permissions_dir = autogenerated.join("commands");
for (command, nested_commands) in COMMANDS {
if nested_commands.is_empty() {
continue;
}

let permission_path = permissions_dir.join(format!("{command}.toml"));

let content = std::fs::read_to_string(&permission_path)
.unwrap_or_else(|_| panic!("failed to read {command}.toml"));

let mut permission_file = toml::from_str::<PermissionFile>(&content)
.unwrap_or_else(|_| panic!("failed to deserialize {command}.toml"));

for p in permission_file
.permission
.iter_mut()
.filter(|p| p.identifier.starts_with("allow"))
{
p.commands
.allow
.extend(nested_commands.iter().map(|s| s.to_string()));
}

let out = toml::to_string_pretty(&permission_file)
.unwrap_or_else(|_| panic!("failed to serialize {command}.toml"));
let out = format!(
r#"# Automatically generated - DO NOT EDIT!
"$schema" = "../../schemas/schema.json"
{out}"#
);
std::fs::write(permission_path, out)
.unwrap_or_else(|_| panic!("failed to write {command}.toml"));
}
}
29 changes: 19 additions & 10 deletions plugins/fs/guest-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ function fromBytes(buffer: FixedSizeArray<number, 8>): number {
const size = bytes.byteLength
let x = 0
for (let i = 0; i < size; i++) {
// eslint-disable-next-line security/detect-object-injection
const byte = bytes[i]
x *= 0x100
x += byte
Expand Down Expand Up @@ -427,11 +428,11 @@ class FileHandle extends Resource {
}

/**
* Writes `p.byteLength` bytes from `p` to the underlying data stream. It
* resolves to the number of bytes written from `p` (`0` <= `n` <=
* `p.byteLength`) or reject with the error encountered that caused the
* Writes `data.byteLength` bytes from `data` to the underlying data stream. It
* resolves to the number of bytes written from `data` (`0` <= `n` <=
* `data.byteLength`) or reject with the error encountered that caused the
* write to stop early. `write()` must reject with a non-null error if
* would resolve to `n` < `p.byteLength`. `write()` must not modify the
* would resolve to `n` < `data.byteLength`. `write()` must not modify the
* slice data, even temporarily.
*
* @example
Expand Down Expand Up @@ -1065,19 +1066,27 @@ interface WriteFileOptions {
*/
async function writeFile(
path: string | URL,
data: Uint8Array,
data: Uint8Array | ReadableStream<Uint8Array>,
options?: WriteFileOptions
): Promise<void> {
if (path instanceof URL && path.protocol !== 'file:') {
throw new TypeError('Must be a file URL.')
}

await invoke('plugin:fs|write_file', data, {
headers: {
path: encodeURIComponent(path instanceof URL ? path.toString() : path),
options: JSON.stringify(options)
if (data instanceof ReadableStream) {
const file = await open(path, options)
for await (const chunk of data) {
await file.write(chunk)
}
})
await file.close()
} else {
await invoke('plugin:fs|write_file', data, {
headers: {
path: encodeURIComponent(path instanceof URL ? path.toString() : path),
options: JSON.stringify(options)
}
})
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,18 @@
[[permission]]
identifier = "allow-read-text-file-lines"
description = "Enables the read_text_file_lines command without any pre-configured scope."
commands.allow = ["read_text_file_lines"]

[permission.commands]
allow = [
"read_text_file_lines",
"read_text_file_lines_next",
]
deny = []

[[permission]]
identifier = "deny-read-text-file-lines"
description = "Denies the read_text_file_lines command without any pre-configured scope."
commands.deny = ["read_text_file_lines"]

[permission.commands]
allow = []
deny = ["read_text_file_lines"]
14 changes: 12 additions & 2 deletions plugins/fs/permissions/autogenerated/commands/write_file.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,19 @@
[[permission]]
identifier = "allow-write-file"
description = "Enables the write_file command without any pre-configured scope."
commands.allow = ["write_file"]

[permission.commands]
allow = [
"write_file",
"open",
"write",
]
deny = []

[[permission]]
identifier = "deny-write-file"
description = "Denies the write_file command without any pre-configured scope."
commands.deny = ["write_file"]

[permission.commands]
allow = []
deny = ["write_file"]
2 changes: 1 addition & 1 deletion plugins/notification/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]

[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
windows = { level = "full", notes = "Only works for installed apps. Shows powershell name & icon in development." }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "full", notes = "" }
Expand Down

0 comments on commit 84950ec

Please sign in to comment.