zudo-text

検索したい単語を入力

いつでも検索バーを開ける

Helper Modules

The helper modules in tauri-app/core/src/helpers/ provide internal Rust utilities for surviving explicitly local native operations and the non-cloud pnpm dev:rest engine. None of these helpers are #[tauri::command].

Caution

Filesystem roots in this page belong to those local compatibility surfaces. They do not define containment or storage for encrypted cloud workspace documents, and they do not imply that the renderer has a local workspace directory. Cloud document paths are workspace-relative keys validated in the backend bridge and workspace model.

safe_path

File: tauri-app/core/src/helpers/safe_path.rs

Prevents directory traversal attacks by validating that a resolved path stays within a given directory.

safe_path(dir, filename) → Result<PathBuf, String>

pub fn safe_path(dir: &str, filename: &str) -> Result<PathBuf, String>

Resolves filename relative to dir and verifies the result doesn't escape the directory boundary.

How it works:

  1. Joins dir and filename into an absolute path

  2. Normalizes both paths lexically (resolving . and .. components without filesystem access)

  3. Checks that the normalized result starts with the normalized directory

  4. Returns an error "Invalid filename" if the path escapes

Examples:

dirfilenameResult
/home/user/projectfile.md/home/user/project/file.md
/home/user/projectsub/file.md/home/user/project/sub/file.md
/home/user/project../../../etc/passwdError: "Invalid filename"
/home/user/project/etc/passwdError: "Invalid filename"

Key design choice: Uses lexical normalization only — no canonicalize() or filesystem access. This means the directory and file need not exist on disk, matching the behavior of Node.js path.resolve().

filename

File: tauri-app/core/src/helpers/filename.rs

Generates timestamped filenames and extracts dates from filename patterns.

generate_filename(name) → String

pub fn generate_filename(name: &str) -> String

Creates a filename in the format YYYYMMDD-slug.md.

Slugification rules:

  1. Lowercase the input

  2. Replace non-ASCII-alphanumeric characters with hyphens

  3. Collapse consecutive hyphens into a single hyphen

  4. Trim leading and trailing hyphens

  5. Use "untitled" if the slug is empty (e.g., all-Japanese input)

Examples:

InputOutput
"Hello World"20260330-hello-world.md
"foo@bar!baz"20260330-foo-bar-baz.md
"テスト"20260330-untitled.md
""20260330-untitled.md

extract_date_from_filename(filename) → Option<String>

pub fn extract_date_from_filename(filename: &str) -> Option<String>

Extracts an ISO date string from a filename. Supports the current format YYYYMMDD-slug.md (returns date only) and the legacy format YYYYMMDD-HHMMSS-slug.md (returns date and time).

Returns: A string in YYYY-MM-DDTHH:MM:SS format, or None if the filename doesn't match.

Examples:

InputOutput
"20250308-143045-hello.md"Some("2025-03-08T14:30:45")
"20250308-1430-hello.md"Some("2025-03-08T14:30:00")
"not-a-date.md"None

frontmatter

File: tauri-app/core/src/helpers/frontmatter.rs

Parses YAML frontmatter from markdown files.

parse_frontmatter(content) → (HashMap<String, String>, String)

pub fn parse_frontmatter(content: &str) -> (HashMap<String, String>, String)

Parses the YAML frontmatter block (delimited by ---) and returns a tuple of metadata key-value pairs and the remaining body.

Supported features:

  • Standard key: value pairs

  • Quoted values (single and double quotes, with escape handling)

  • YAML multi-line scalars (>-, >, |-, |) — continuation lines are joined with spaces

  • CRLF normalization (Windows-compatible)

Returns: If no frontmatter is found, returns an empty HashMap and the original content as the body.

Example:

---
title: Hello World
description: >-
  A long description
  that spans lines
sidebar_position: 5
---
Body content here

Produces:

  • { "title": "Hello World", "description": "A long description that spans lines", "sidebar_position": "5" }

  • Body: "Body content here"

strip_frontmatter(content) → String

pub fn strip_frontmatter(content: &str) -> String

Removes the frontmatter block and returns only the body. If no frontmatter is present, returns the original content unchanged.

pin_path

File: tauri-app/core/src/helpers/pin_path.rs

Resolves pin directory paths with traversal protection.

resolve_pin_path(project_root, pin_path) → Result<Option<PathBuf>, String>

pub fn resolve_pin_path(project_root: &str, pin_path: &str) -> Result<Option<PathBuf>, String>

Resolves a pin path from settings to an absolute directory path.

Rules:

InputBehavior
Empty or blankReturns Ok(None) — pin not configured
Absolute path (e.g., /usr/docs)Returned directly — user chose via file picker
Relative path (e.g., docs/api)Resolved relative to project root, with traversal check
Traversal (e.g., ../../etc)Returns Err("Pin path escapes project root: ...")

Traversal prevention: Like safe_path, uses lexical normalization without filesystem access.

pin_tree (local-engine compatibility)

File: tauri-app/core/src/helpers/pin_tree.rs

Builds file/directory listings within a local pin directory. The shallow one-level function backs the retained development HTTP server. The deep recursive function remains as a backward-compatibility primitive. Neither is a cloud-workspace renderer contract or a registered Tauri pin command.

PinEntry structure:

interface PinEntry {
  name: string;            // Filename or directory name
  type: 'file' | 'directory';
  path: string;            // Relative path from pin root
  title: string;           // From frontmatter name > title > filename stem
  description: string;     // From frontmatter description, or ""
  modifiedAt: string;      // ISO 8601 (files only)
  children?: PinEntry[];   // Only present in deep (list_pin_tree) mode
  hasChildren?: boolean;   // Set for directories in shallow mode; absent otherwise
}

Title resolution for files: Prefers the name frontmatter key, falls back to title, then to the filename without the .md extension.

list_dir_one_level(pin_dir, relative_path) → Vec<PinEntry>

pub fn list_dir_one_level(pin_dir: &Path, relative_path: &str) -> Vec<PinEntry>

Lists only the immediate children of relative_path within pin_dir — does not recurse. The local development HTTP routes use it to implement lazy expansion.

Behavior:

  • Only includes .md files and directories; skips dotfiles and non-markdown files

  • For directories, sets hasChildren: true/false (one-level scan only — does not recurse) but does not populate children

  • For files, reads frontmatter to resolve title and description

  • Directories come first, then alphabetically within each group

list_pin_tree(pin_dir, relative_path) → Vec<PinEntry>

pub fn list_pin_tree(pin_dir: &Path, relative_path: &str) -> Vec<PinEntry>

Recursively lists the full tree within pin_dir. It is retained for backward compatibility but is not called by the cloud adapters or registered as a Tauri command.

Filtering rules:

  • Only includes .md files; skips dotfiles and empty directories

  • Recursion limited to depth 10

  • Silently skips entries with permission errors or missing directories

path_containment

File: tauri-app/core/src/helpers/path_containment.rs

Guards filesystem-mutating commands against path-escape attacks by verifying a requested path is contained within at least one allowed root.

validate_path_in_roots(path, allowed_roots) → Result<PathBuf, String>

pub fn validate_path_in_roots(path: &str, allowed_roots: &[&Path]) -> Result<PathBuf, String>

Checks that path, after lexical normalization, is a sub-path of at least one entry in allowed_roots. Returns the normalized PathBuf on success, or an error message on failure.

Used by: files_delete_file and fs_mkdir Tauri commands, so they cannot act as generic filesystem write/delete primitives outside the workspace and user-skills directories.

Examples:

pathallowed_rootsResult
/workspace/skills/foo.md["/workspace"]Ok(normalized path)
/workspace/../../../etc/passwd["/workspace"]Err("…not within any allowed root")
/etc/passwd["/workspace"]Err(…)

Design note: Uses lexical normalization only — symlinks inside an allowed root that point outside it would pass the check. This is intentional: the allowed roots are user-owned directories; the guard is against ../absolute-path escapes in the path string, not against hostile filesystem layouts.

watcher_dedup

File: tauri-app/core/src/helpers/watcher_dedup.rs

Pure helper for deduplicating file-watcher observations collected within a debounce window.

dedupe_changes(observations) → Vec<(String, String)>

pub fn dedupe_changes(observations: &[(String, String)]) -> Vec<(String, String)>

Deduplicates a flat slice of (path, kind) pairs, preserving first-seen order.

Deduplication key: (path, kind) — two events for the same path with different kinds (e.g., "removed" then "added") are treated as distinct and both emitted.

Used by: the skills-watcher debounce logic in tauri-app/src/commands/watchers.rs.

Example:

let events = vec![
    ("/skills/a.md".into(), "updated".into()),
    ("/skills/a.md".into(), "updated".into()), // duplicate — collapsed
    ("/skills/b.md".into(), "added".into()),
];
let result = dedupe_changes(&events);
// [("/skills/a.md", "updated"), ("/skills/b.md", "added")]

path_utils

File: tauri-app/core/src/helpers/path_utils.rs

Provides low-level path utilities used by other helpers (e.g., safe_path uses normalize_path internally).

mtime_ms(path) → u64

pub fn mtime_ms(path: &Path) -> u64

Returns the file's modification time in milliseconds since the UNIX epoch. Returns 0 if the file doesn't exist or the metadata can't be read (no panics).

How it works:

  1. Reads the file metadata via fs::metadata

  2. Extracts the modified() timestamp

  3. Converts from SystemTime to milliseconds since UNIX_EPOCH

  4. Returns 0 on any error in the chain

normalize_path(path) → PathBuf

pub fn normalize_path(path: &PathBuf) -> PathBuf

Resolves . and .. components in a path lexically — without requiring filesystem access. This means the path need not exist on disk.

Rules:

ComponentBehavior
. (current dir)Removed
.. (parent dir)Pops the previous component
Anything elseKept as-is

Example:

InputOutput
/home/user/./docs/../file.md/home/user/file.md
a/b/../ca/c