Backend: File System Operations
Relevant source files
The following files were used as context for generating this wiki page:The file system operations in Scripty are a critical part of its architecture, managed by a combination of a Rust backend using Tauri and a JavaScript frontend. The backend is responsible for direct file interactions, such as reading user-selected PowerShell scripts and managing embedded executables. The frontend leverages Tauri's API to persist application state (like script metadata and tags) into a local JSON file and to invoke the backend's file-reading capabilities.
This system enables Scripty to load external scripts for execution, maintain user data across sessions, and manage its own dependencies, forming the foundation of the application's script management features. All file system access is governed by a strict set of permissions defined in the Tauri capabilities configuration.
Core Components
Rust Backend (Tauri Commands)
The Rust backend exposes several functions as Tauri "commands" that can be invoked from the JavaScript frontend. These commands handle direct interactions with the host machine's file system and processes.
Sources: src-tauri/src/lib.rs
File Reading Command: read_ps1
This is the primary command for reading script files. It takes a file path as input, reads the entire file into a string, and returns the path and its content to the frontend.
// src-tauri/src/lib.rs:59-65
#[tauri::command]
fn read_ps1(path: String) -> Result<(String, String), String> {
match fs::read_to_string(&path) {
Ok(content) => Ok((path, content)),
Err(_e) => Err(format!("Failed to resolve the .ps1 file")),
}
}
Sources: src-tauri/src/lib.rs:59-65
| Parameter | Type | Description |
|---|---|---|
path | String | The absolute path to the .ps1 file. |
| Return | Result<(String, String), String> | On success, returns a tuple containing the original path and the file content. On failure, returns an error message string. |
| Sources: src-tauri/src/lib.rs:60-64 |
Embedded Executable Management
Scripty includes an embedded syspwsh.exe binary. The extract_syspwsh function is responsible for writing this binary to the user's temporary directory if it doesn't already exist. This ensures the executable is available to be called by the run_sys_terminal command.
This diagram illustrates the logic for extracting the embedded syspwsh.exe.
Sources: src-tauri/src/lib.rs:9-21
The Rust code for this extraction logic is as follows:
// src-tauri/src/lib.rs:9-21
fn extract_syspwsh() -> Result<std::path::PathBuf, String> {
let mut temp_path = env::temp_dir();
temp_path.push("syspwsh.exe");
// Write only if missing or update if you want to overwrite every time
if !temp_path.exists() {
let mut file = File::create(&temp_path).map_err(|e| e.to_string())?;
file.write_all(SYSPWSH_EXE).map_err(|e| e.to_string())?;
}
Ok(temp_path)
}
Sources: src-tauri/src/lib.rs:9-21
Frontend State Persistence
The application's state, including the list of scripts and user-defined tags, is managed by zustand. To persist this state, a custom storage adapter is implemented using the @tauri-apps/plugin-fs package. This adapter reads from and writes to a scriptStorage.json file located in the application's data directory.
Sources: src/Hooks/useListStore.js
fileStorage Adapter
The fileStorage object provides an interface for zustand's persist middleware, mapping getItem, setItem, and removeItem to Tauri's file system APIs.
// src/Hooks/useListStore.js:12-26
const fileStorage = {
getItem: async (_) => {
const path = await getFileStorePath();
if (!(await exists(path))) return null;
return await readTextFile(path);
},
setItem: async (_, value) => {
const path = await getFileStorePath();
await writeTextFile(path, value);
},
removeItem: async (_) => {
const path = await getFileStorePath();
await writeTextFile(path, "");
},
};
Sources: src/Hooks/useListStore.js:12-26
This diagram shows the flow of how application state is saved to the file system.
Sources: src/Hooks/useListStore.js:7-26
Data Flow: Loading a PowerShell Script
The process of adding a new script involves both the frontend and backend. The user initiates the action from the UI, which opens a native file dialog. Upon selection, the file path is sent to the Rust backend to be read, and the content is returned to the frontend to be stored in the application state.
This sequence diagram details the interaction between the user, the frontend components, and the backend.
File System Permissions
Tauri's security model requires that all file system capabilities be explicitly declared. The default.json capability file for Scripty grants a wide range of permissions, which are essential for its functionality. This includes writing to the app-specific data directory for state persistence and reading user-selected files.
Key permissions include:
| Permission | Description |
|---|---|
fs:default | Default set of file system permissions. |
fs:allow-appdata-write-recursive | Allows writing recursively to the application's data directory. Crucial for scriptStorage.json. |
fs:allow-temp-write-recursive | Allows writing recursively to the system's temporary directory. Used for syspwsh.exe. |
fs:allow-write-text-file | A specific permission to allow writing text files. |
fs:write-all | Broad permission to write files. |
Sources: src-tauri/capabilities/default.json:13-60
Summary
Scripty's file system operations are a well-defined and secure part of the application, split between a Rust backend for privileged operations and a JavaScript frontend for state management and user interaction. The backend exposes specific Tauri commands like read_ps1 to safely read files from the user's disk. The frontend uses Tauri's FS plugin to persist application state to a dedicated JSON file. This clear separation of concerns, governed by an explicit permissions model, allows Scripty to be both functional and secure in its handling of local files.