Feature: Script Management (CRUD)
Relevant source files
The following files were used as context for generating this wiki page:The Script Management feature is the core functionality of the (S)cripty application, providing users with the ability to create, read, delete, and execute PowerShell scripts. This system is built using a React frontend, which handles the user interface, and a Tauri backend written in Rust, which manages file system interactions and script execution.
Client-side state, including the list of scripts and tags, is managed by a Zustand store (useListStore). This store persists its data to a local JSON file (scriptStorage.json) in the application's data directory, ensuring that user data is retained between sessions. The UI is composed of several key components: a form for adding new scripts (Form.jsx), a list to display existing scripts (List.jsx), and a detailed view (DetailView.jsx) for inspecting, running, and deleting a selected script.
Architecture Overview
The feature's architecture separates the UI, state management, and backend operations. React components trigger actions on the Zustand store, which updates the application state. For operations requiring native capabilities, such as reading files or executing commands, the frontend invokes functions exposed by the Tauri Rust backend.
This diagram illustrates the high-level interaction between the main components of the script management feature.
State Management (useListStore)
All client-side data for scripts and tags is managed by a central Zustand store defined in useListStore.js. This store is the single source of truth for the application's script data.
Sources: src/Hooks/useListStore.js
State Structure
The store maintains the list of all script items, available tags, the currently selected item for the detail view, and any active filters.
| Key | Type | Description |
|---|---|---|
items | Array<Object> | An array of script objects. |
tags | Array<string> | An array of available tags. Initialized with default values. |
selectedItem | Object | null | The script object currently being viewed in DetailView. |
filterTag | string | null | The tag used to filter the script list. |
Sources: src/Hooks/useListStore.js:25-31
A script item object has the following structure:
{
title: "IP Config",
content: "Get-NetIPAddress...",
tags: ["Check", "Routine"],
date: "M/D/YYYY",
id: "a-unique-uuid"
}
Sources: src/components/Form/Form.jsx:60-66
Actions
The store exposes several actions to manipulate the state. These actions are called from the React components to perform CRUD operations.
| Action | Parameters | Description |
|---|---|---|
addItem | item | Adds a new script object to the items array. |
addTag | tag | Adds a new tag to the tags array if it doesn't already exist. |
removeItem | id | Removes a script from the items array by its id. |
selectItem | item | Sets the selectedItem to the provided script object. |
clearSelection | - | Resets selectedItem to null. |
setFilterTag | tag | Sets the filterTag to filter the list of scripts. |
getFilteredItems | - | Returns a filtered list of items based on the current filterTag, excluding "Archive" by default. |
Sources: src/Hooks/useListStore.js:33-69
Data Persistence
The store's state (items and tags) is automatically persisted to the local file system using Zustand's persist middleware. A custom storage implementation leverages the @tauri-apps/plugin-fs to write and read the state to a scriptStorage.json file located in the user's app data directory.
The following diagram shows the data persistence flow.
Creating a Script (Create)
A new script is created via the Form component. The user provides a name, selects tags, and then chooses a .ps1 file from their local system. The file's content is read and stored along with the metadata.
The sequence diagram below details the creation process.
Reading and Viewing Scripts (Read)
Scripts are displayed in the List component, which retrieves them from the useListStore. The list can be filtered by tags. Clicking on a script in the list opens the DetailView component to show its content and provide further actions.
Script Listing and Filtering
The List.jsx component renders a ListItem for each script returned by the getFilteredItems() function from the store. This function applies the currently selected filterTag.
Sources: src/components/Form/List.jsx:32-34, src/Hooks/useListStore.js:59-69
Detail View
When a user clicks a ListItem, two actions occur:
- The
selectItemaction inuseListStoreis called with the clicked script, setting it as theselectedItem. - The
DetailViewcomponent is made visible.
The DetailView component reads selectedItem from the store and displays its title and content.
This flow is illustrated below.
Deleting a Script (Delete)
Scripts can be deleted from the DetailView. This action prompts the user for confirmation before removing the script from the state.
The deleteItem function in DetailView.jsx orchestrates this process:
- It uses
@tauri-apps/plugin-dialog'saskfunction to show a confirmation dialog. - If the user confirms, it calls the
removeItem(selectedItem.id)action fromuseListStore. - The
DetailViewis then hidden.
Script Execution
While not a standard CRUD operation, script execution is a primary function. From the DetailView, a user can run the selected script with different privilege levels (User or Admin).
The chruntime function in DetailView.jsx invokes a specific Tauri command based on the user's selection from a dropdown.
Backend Commands
The Rust backend provides several commands for running PowerShell scripts. These are exposed to the frontend via tauri::generate_handler!.
| Command | Parameters | Description |
|---|---|---|
open_terminal | content: String | Spawns a new PowerShell process and passes the script content to it. Runs as the current user. |
open_admin_terminal | content: String | Spawns a new PowerShell process with elevated (Administrator) privileges using Start-Process -Verb RunAs. |
run_sys_terminal | content: String | Executes a script as the NT AUTHORITY\SYSTEM user by extracting and running an embedded syspwsh.exe. |
read_ps1 | path: String | Reads the content of a text file (e.g., .ps1) from the given path and returns it to the frontend. |
Sources: src-tauri/src/lib.rs:29-71, src/components/DetailView/DetailView.jsx:15-28
Tag Management
Users can create custom tags to organize their scripts. The FormTag.jsx component provides a simple form to add a new tag. Submitting the form calls the addTag action in useListStore, which adds the new tag to the global tags array if it's not a duplicate. These tags then become available in the script creation form (Form.jsx).
Sources: src/components/Form/FormTag.jsx:7-12, src/Hooks/useListStore.js:39-43