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

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
Amr Bashir 2021-08-02 15:58:09 +02:00 committed by GitHub
parent 1a51006673
commit 05b9d81ee6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 406 additions and 74 deletions

View File

@ -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.

View File

@ -100,7 +100,8 @@ api-all = [
"shell-all", "shell-all",
"os-all", "os-all",
"dialog-all", "dialog-all",
"updater" "updater",
"path-all"
] ]
updater = [ "minisign-verify", "base64" ] updater = [ "minisign-verify", "base64" ]
menu = [ "tauri-runtime/menu", "tauri-runtime-wry/menu" ] menu = [ "tauri-runtime/menu", "tauri-runtime-wry/menu" ]
@ -117,7 +118,7 @@ fs-create-dir = [ ]
fs-remove-dir = [ ] fs-remove-dir = [ ]
fs-remove-file = [ ] fs-remove-file = [ ]
fs-rename-file = [ ] fs-rename-file = [ ]
fs-path = [ ] path-all = [ ]
window-all = [ ] window-all = [ ]
window-create = [ ] window-create = [ ]
shell-all = [ "shell-open", "shell-execute" ] shell-all = [ "shell-open", "shell-execute" ]

View File

@ -23,7 +23,6 @@ fn main() {
fs_remove_dir: { any(fs_all, feature = "fs-remove-dir") }, fs_remove_dir: { any(fs_all, feature = "fs-remove-dir") },
fs_remove_file: { any(fs_all, feature = "fs-remove-file") }, fs_remove_file: { any(fs_all, feature = "fs-remove-file") },
fs_rename_file: { any(fs_all, feature = "fs-rename-file") }, fs_rename_file: { any(fs_all, feature = "fs-rename-file") },
fs_path: { any(fs_all, feature = "fs-path") },
// window // window
window_all: { any(api_all, feature = "window-all") }, window_all: { any(api_all, feature = "window-all") },
@ -54,5 +53,8 @@ fn main() {
// os // os
os_all: { any(api_all, feature = "os-all") }, os_all: { any(api_all, feature = "os-all") },
// path
path_all: { any(api_all, feature = "path-all") },
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -25,6 +25,7 @@ mod http;
mod internal; mod internal;
mod notification; mod notification;
mod operating_system; mod operating_system;
mod path;
mod process; mod process;
mod shell; mod shell;
mod window; mod window;
@ -49,6 +50,7 @@ enum Module {
Process(process::Cmd), Process(process::Cmd),
Fs(file_system::Cmd), Fs(file_system::Cmd),
Os(operating_system::Cmd), Os(operating_system::Cmd),
Path(path::Cmd),
Window(Box<window::Cmd>), Window(Box<window::Cmd>),
Shell(shell::Cmd), Shell(shell::Cmd),
Event(event::Cmd), Event(event::Cmd),
@ -84,6 +86,12 @@ impl Module {
.and_then(|r| r.json) .and_then(|r| r.json)
.map_err(InvokeError::from) .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 Self::Os(cmd) => resolver
.respond_async(async move { cmd.run().and_then(|r| r.json).map_err(InvokeError::from) }), .respond_async(async move { cmd.run().and_then(|r| r.json).map_err(InvokeError::from) }),
Self::Window(cmd) => resolver.respond_async(async move { Self::Window(cmd) => resolver.respond_async(async move {

View File

@ -93,11 +93,6 @@ pub enum Cmd {
new_path: PathBuf, new_path: PathBuf,
options: Option<FileOperationOptions>, options: Option<FileOperationOptions>,
}, },
/// The resolve path API
ResolvePath {
path: String,
directory: Option<BaseDirectory>,
},
} }
impl Cmd { impl Cmd {
@ -201,13 +196,6 @@ impl Cmd {
Self::RenameFile { .. } => Err(crate::Error::ApiNotAllowlisted( Self::RenameFile { .. } => Err(crate::Error::ApiNotAllowlisted(
"fs > renameFile".to_string(), "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())),
} }
} }
} }
@ -405,16 +393,6 @@ pub fn read_binary_file(
.map_err(crate::Error::FailedToExecuteApi) .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. // test webview functionality.
#[cfg(test)] #[cfg(test)]
mod test { mod test {

View File

@ -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(),
))),
}
}

View File

@ -9,6 +9,7 @@ import { invoke } from '../tauri'
type TauriModule = type TauriModule =
| 'App' | 'App'
| 'Fs' | 'Fs'
| 'Path'
| 'Os' | 'Os'
| 'Window' | 'Window'
| 'Shell' | 'Shell'

View File

@ -4,9 +4,10 @@
import { invokeTauriCommand } from './helpers/tauri' import { invokeTauriCommand } from './helpers/tauri'
import { BaseDirectory } from './fs' import { BaseDirectory } from './fs'
import { isWindows } from './helpers/os-check'
/** /**
* Read common system paths such as home, config and cache directories. * The path module provides utilities for working with file and directory paths.
* *
* This package is also accessible with `window.__TAURI__.path` when `tauri.conf.json > build > withGlobalTauri` is set to true. * This package is also accessible with `window.__TAURI__.path` when `tauri.conf.json > build > withGlobalTauri` is set to true.
* *
@ -15,9 +16,8 @@ import { BaseDirectory } from './fs'
* { * {
* "tauri": { * "tauri": {
* "allowlist": { * "allowlist": {
* "fs": { * "path": {
* "all": true, // enable all FS APIs * "all": true, // enable all Path APIs
* "path": true // enable path APIs
* } * }
* } * }
* } * }
@ -35,7 +35,7 @@ import { BaseDirectory } from './fs'
*/ */
async function appDir(): Promise<string> { async function appDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -57,7 +57,7 @@ async function appDir(): Promise<string> {
*/ */
async function audioDir(): Promise<string> { async function audioDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -79,7 +79,7 @@ async function audioDir(): Promise<string> {
*/ */
async function cacheDir(): Promise<string> { async function cacheDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -101,7 +101,7 @@ async function cacheDir(): Promise<string> {
*/ */
async function configDir(): Promise<string> { async function configDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -123,7 +123,7 @@ async function configDir(): Promise<string> {
*/ */
async function dataDir(): Promise<string> { async function dataDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -145,7 +145,7 @@ async function dataDir(): Promise<string> {
*/ */
async function desktopDir(): Promise<string> { async function desktopDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -167,7 +167,7 @@ async function desktopDir(): Promise<string> {
*/ */
async function documentDir(): Promise<string> { async function documentDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -189,7 +189,7 @@ async function documentDir(): Promise<string> {
*/ */
async function downloadDir(): Promise<string> { async function downloadDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -211,7 +211,7 @@ async function downloadDir(): Promise<string> {
*/ */
async function executableDir(): Promise<string> { async function executableDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -233,7 +233,7 @@ async function executableDir(): Promise<string> {
*/ */
async function fontDir(): Promise<string> { async function fontDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -255,7 +255,7 @@ async function fontDir(): Promise<string> {
*/ */
async function homeDir(): Promise<string> { async function homeDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -277,7 +277,7 @@ async function homeDir(): Promise<string> {
*/ */
async function localDataDir(): Promise<string> { async function localDataDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -299,7 +299,7 @@ async function localDataDir(): Promise<string> {
*/ */
async function pictureDir(): Promise<string> { async function pictureDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -321,7 +321,7 @@ async function pictureDir(): Promise<string> {
*/ */
async function publicDir(): Promise<string> { async function publicDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -337,7 +337,7 @@ async function publicDir(): Promise<string> {
*/ */
async function resourceDir(): Promise<string> { async function resourceDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -359,7 +359,7 @@ async function resourceDir(): Promise<string> {
*/ */
async function runtimeDir(): Promise<string> { async function runtimeDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -381,7 +381,7 @@ async function runtimeDir(): Promise<string> {
*/ */
async function templateDir(): Promise<string> { async function templateDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -403,7 +403,7 @@ async function templateDir(): Promise<string> {
*/ */
async function videoDir(): Promise<string> { async function videoDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -419,7 +419,7 @@ async function videoDir(): Promise<string> {
*/ */
async function currentDir(): Promise<string> { async function currentDir(): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolvePath',
path: '', path: '',
@ -429,22 +429,110 @@ async function currentDir(): Promise<string> {
} }
/** /**
* Resolves the path with the optional base directory. * Provides the platform-specific path segment separator:
* * - `\` on Windows
* @param path A path to resolve * - `/` on POSIX
* @param directory A base directory to use when resolving the given path
* @returns A path resolved to the given base directory.
*/ */
async function resolvePath( const sep = isWindows() ? '\\' : '/'
path: string,
directory: BaseDirectory /**
): Promise<string> { * Provides the platform-specific path segment delimiter:
* - `;` on Windows
* - `:` on POSIX
*/
const delimiter = isWindows() ? ';' : ':'
/**
* Resolves a sequence of `paths` or `path` segments into an absolute path.
*
* @param paths A sequence of paths or path segments.
*/
async function resolve(...paths: string[]): Promise<string> {
return invokeTauriCommand<string>({ return invokeTauriCommand<string>({
__tauriModule: 'Fs', __tauriModule: 'Path',
message: { message: {
cmd: 'resolvePath', cmd: 'resolve',
paths
}
})
}
/**
* Normalizes the given `path`, resolving `'..'` and `'.'` segments and resolve symolic links.
*/
async function normalize(path: string): Promise<string> {
return invokeTauriCommand<string>({
__tauriModule: 'Path',
message: {
cmd: 'normalize',
path
}
})
}
/**
* Joins all given `path` segments together using the platform-specific separator as a delimiter, then normalizes the resulting path.
*
* @param paths A sequence of path segments.
*/
async function join(...paths: string[]): Promise<string> {
return invokeTauriCommand<string>({
__tauriModule: 'Path',
message: {
cmd: 'join',
paths
}
})
}
/**
* Returns the directory name of a `path`. Trailing directory separators are ignored.
*/
async function dirname(path: string): Promise<string> {
return invokeTauriCommand<string>({
__tauriModule: 'Path',
message: {
cmd: 'dirname',
path
}
})
}
/**
* Returns the extension of the `path`.
*/
async function extname(path: string): Promise<string> {
return invokeTauriCommand<string>({
__tauriModule: 'Path',
message: {
cmd: 'extname',
path
}
})
}
/**
* Returns the last portion of a `path`. Trailing directory separators are ignored.
*
* @param ext An optional file extension to be removed from the returned path.
*/
async function basename(path: string, ext?: string): Promise<string> {
return invokeTauriCommand<string>({
__tauriModule: 'Path',
message: {
cmd: 'basename',
path, path,
directory ext
}
})
}
async function isAbsolute(path: string): Promise<boolean> {
return invokeTauriCommand<boolean>({
__tauriModule: 'Path',
message: {
cmd: 'isAbsolute',
path
} }
}) })
} }
@ -469,6 +557,14 @@ export {
templateDir, templateDir,
videoDir, videoDir,
currentDir, currentDir,
resolvePath, BaseDirectory,
BaseDirectory sep,
delimiter,
resolve,
normalize,
join,
dirname,
extname,
basename,
isAbsolute
} }

View File

@ -380,8 +380,6 @@ pub struct FsAllowlistConfig {
pub remove_file: bool, pub remove_file: bool,
#[serde(default)] #[serde(default)]
pub rename_file: bool, pub rename_file: bool,
#[serde(default)]
pub path: bool,
} }
impl Allowlist for FsAllowlistConfig { impl Allowlist for FsAllowlistConfig {
@ -400,7 +398,6 @@ impl Allowlist for FsAllowlistConfig {
check_feature!(self, features, remove_dir, "fs-remove-dir"); check_feature!(self, features, remove_dir, "fs-remove-dir");
check_feature!(self, features, remove_file, "fs-remove-file"); check_feature!(self, features, remove_file, "fs-remove-file");
check_feature!(self, features, rename_file, "fs-rename-file"); check_feature!(self, features, rename_file, "fs-rename-file");
check_feature!(self, features, path, "fs-path");
features features
} }
} }
@ -530,6 +527,40 @@ impl Allowlist for GlobalShortcutAllowlistConfig {
} }
} }
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct OsAllowlistConfig {
#[serde(default)]
pub all: bool,
}
impl Allowlist for OsAllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["os-all"]
} else {
vec![]
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct PathAllowlistConfig {
#[serde(default)]
pub all: bool,
}
impl Allowlist for PathAllowlistConfig {
fn to_features(&self) -> Vec<&str> {
if self.all {
vec!["path-all"]
} else {
vec![]
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)] #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct AllowlistConfig { pub struct AllowlistConfig {
@ -549,6 +580,10 @@ pub struct AllowlistConfig {
pub notification: NotificationAllowlistConfig, pub notification: NotificationAllowlistConfig,
#[serde(default)] #[serde(default)]
pub global_shortcut: GlobalShortcutAllowlistConfig, pub global_shortcut: GlobalShortcutAllowlistConfig,
#[serde(default)]
pub os: OsAllowlistConfig,
#[serde(default)]
pub path: PathAllowlistConfig,
} }
impl Allowlist for AllowlistConfig { impl Allowlist for AllowlistConfig {
@ -564,6 +599,8 @@ impl Allowlist for AllowlistConfig {
features.extend(self.http.to_features()); features.extend(self.http.to_features());
features.extend(self.notification.to_features()); features.extend(self.notification.to_features());
features.extend(self.global_shortcut.to_features()); features.extend(self.global_shortcut.to_features());
features.extend(self.os.to_features());
features.extend(self.path.to_features());
features features
} }
} }

View File

@ -49,7 +49,6 @@
"all": false, "all": false,
"copyFile": false, "copyFile": false,
"createDir": false, "createDir": false,
"path": false,
"readBinaryFile": false, "readBinaryFile": false,
"readDir": false, "readDir": false,
"readTextFile": false, "readTextFile": false,
@ -69,6 +68,12 @@
"notification": { "notification": {
"all": false "all": false
}, },
"os": {
"all": false
},
"path": {
"all": false
},
"shell": { "shell": {
"all": false, "all": false,
"execute": false, "execute": false,
@ -133,7 +138,6 @@
"all": false, "all": false,
"copyFile": false, "copyFile": false,
"createDir": false, "createDir": false,
"path": false,
"readBinaryFile": false, "readBinaryFile": false,
"readDir": false, "readDir": false,
"readTextFile": false, "readTextFile": false,
@ -180,6 +184,26 @@
} }
] ]
}, },
"os": {
"default": {
"all": false
},
"allOf": [
{
"$ref": "#/definitions/OsAllowlistConfig"
}
]
},
"path": {
"default": {
"all": false
},
"allOf": [
{
"$ref": "#/definitions/PathAllowlistConfig"
}
]
},
"shell": { "shell": {
"default": { "default": {
"all": false, "all": false,
@ -724,10 +748,6 @@
"default": false, "default": false,
"type": "boolean" "type": "boolean"
}, },
"path": {
"default": false,
"type": "boolean"
},
"readBinaryFile": { "readBinaryFile": {
"default": false, "default": false,
"type": "boolean" "type": "boolean"
@ -846,6 +866,16 @@
}, },
"additionalProperties": false "additionalProperties": false
}, },
"OsAllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
},
"PackageConfig": { "PackageConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -866,6 +896,16 @@
}, },
"additionalProperties": false "additionalProperties": false
}, },
"PathAllowlistConfig": {
"type": "object",
"properties": {
"all": {
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
},
"SecurityConfig": { "SecurityConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -930,7 +970,6 @@
"all": false, "all": false,
"copyFile": false, "copyFile": false,
"createDir": false, "createDir": false,
"path": false,
"readBinaryFile": false, "readBinaryFile": false,
"readDir": false, "readDir": false,
"readTextFile": false, "readTextFile": false,
@ -950,6 +989,12 @@
"notification": { "notification": {
"all": false "all": false
}, },
"os": {
"all": false
},
"path": {
"all": false
},
"shell": { "shell": {
"all": false, "all": false,
"execute": false, "execute": false,

View File

@ -135,7 +135,6 @@ pub fn all_allowlist_features() -> Vec<&'static str> {
remove_dir: true, remove_dir: true,
remove_file: true, remove_file: true,
rename_file: true, rename_file: true,
path: true,
}, },
window: WindowAllowlistConfig { window: WindowAllowlistConfig {
all: true, all: true,
@ -157,6 +156,8 @@ pub fn all_allowlist_features() -> Vec<&'static str> {
}, },
notification: NotificationAllowlistConfig { all: true }, notification: NotificationAllowlistConfig { all: true },
global_shortcut: GlobalShortcutAllowlistConfig { all: true }, global_shortcut: GlobalShortcutAllowlistConfig { all: true },
os: OsAllowlistConfig { all: true },
path: PathAllowlistConfig { all: true },
} }
.to_features() .to_features()
} }