Skip to main content

NoteVault

Struct NoteVault 

Source
pub struct NoteVault { /* private fields */ }
Expand description

Facade over a vault: a directory of Markdown notes plus its searchable index. Cheap to clone — clones share the index pool and per-note locks.

Implementations§

Source§

impl NoteVault

Source

pub async fn new(config: VaultConfig) -> Result<Self, VaultError>

Creates a new instance of the Note Vault. Make sure you call NoteVault::validate_and_init(&self) to initialize the DB index if needed.

Source

pub fn workspace_path(&self) -> &Path

OS path to the workspace root (filesystem root of this vault).

Source

pub fn index_ready(&self) -> bool

false when opening the vault self-healed the index schema (missing, outdated, or invalid), meaning the index is valid but empty until a sync pass (validate_and_init) fills it. Fast paths use this to refuse to operate against an empty index without paying for a sync.

Source

pub async fn validate_and_init(&self) -> Result<IndexReport, VaultError>

Brings the index in step with the vault on disk. Opening the vault already self-healed the index schema, so all that remains is a sync pass: a quick existence scan when the index was already current, or a full scan when it was just healed (and is thus empty). This can be slow on large vaults.

Source

pub async fn recreate_index(&self) -> Result<IndexReport, VaultError>

Deletes all the cached data from the index by recreating its schema, then rebuilds it with a full sync pass.

Source

pub async fn index_notes( &self, validation_mode: NotesValidation, ) -> Result<IndexReport, VaultError>

Traverses the whole vault directory and verifies the notes to update the cached data in the DB. The validation is defined by the validation mode:

NotesValidation::Full Checks the content of the note by comparing a hash based on the text conatined in the file. NotesValidation::Fast Checks the size of the file to identify if the note has changed and then update the DB entry. NotesValidation::None Checks if the note exists or not.

Source

pub async fn exists(&self, path: &VaultPath) -> bool

Returns true if the path resolves to anything (note, directory, attachment) on disk. Cheaper than loading the full entry when only existence matters.

Source

pub fn journal_path(&self) -> &VaultPath

Directory under which journal entries are created.

Source

pub fn inbox_path(&self) -> &VaultPath

Directory under which quick-capture notes are created.

Source

pub fn set_inbox_path(&mut self, path: VaultPath)

Overrides the inbox directory used by Self::quick_note.

Source

pub async fn quick_note(&self, text: &str) -> Result<NoteDetails, VaultError>

Creates a timestamped note under the inbox directory. On name collision (including TOCTOU between the in-memory probe and the FS create), tries the next suffix up to -99. The retry loop calls create_note directly so each iteration’s existence check is the atomic O_EXCL open inside nfs::create_note_exclusive.

Source

pub async fn journal_entry( &self, ) -> Result<(NoteDetails, String, bool), VaultError>

Loads today’s journal entry, creating it with a date heading if it does not exist yet. Returns the note details, its content, and true when the entry was freshly created.

Source

pub fn journal_date(&self, note_path: &VaultPath) -> Option<NaiveDate>

Parses the date out of a journal note path, or None when note_path is not a YYYY-MM-DD note directly under the journal directory.

Source

pub async fn load_or_create_note( &self, path: &VaultPath, default_text: Option<String>, ) -> Result<(String, bool), VaultError>

Loads the note at path if it exists; otherwise creates it with default_text (or empty if None) and returns that text. Returns the note’s text and true when the note had to be created (it did not exist yet), so callers can react to a fresh note — e.g. refresh a directory listing.

Source

pub async fn get_note_text( &self, path: &VaultPath, ) -> Result<String, VaultError>

Loads the raw text of the note at path.

When the file doesn’t exist you get a VaultError::FSError wrapping FSError::NotePathNotFound; you can branch on that to lazily create a note, or use Self::load_or_create_note instead.

Source

pub async fn load_note( &self, path: &VaultPath, ) -> Result<NoteDetails, VaultError>

Loads a note as NoteDetails, carrying its path, raw text, and parsed metadata.

Missing-file behaviour matches Self::get_note_text.

Source

pub async fn get_note_chunks( &self, path: &VaultPath, ) -> Result<HashMap<VaultPath, Vec<ContentChunk>>, VaultError>

Returns the indexed content chunks for the note at path, keyed by the note path they belong to.

Source

pub async fn search_notes<S: AsRef<str>>( &self, search_query: S, ) -> Result<Vec<(NoteEntryData, NoteContentData)>, VaultError>

Searches notes using the vault’s query syntax (see SearchTerms). Returns each matching note’s entry and content data.

Source

pub async fn list_labels(&self) -> Result<Vec<String>, VaultError>

Returns every distinct label persisted in the vault, lowercased.

Source

pub async fn suggest_notes_by_prefix( &self, prefix: &str, limit: usize, ) -> Result<Vec<NoteSuggestion>, VaultError>

Returns notes whose name (filename without extension) starts with prefix, case-insensitive, capped at limit. Used to feed the wikilink autocomplete popup — note that the inserted wikilink target is the name field, not the path.

Source

pub async fn suggest_tags_by_prefix( &self, prefix: &str, limit: usize, ) -> Result<Vec<TagSuggestion>, VaultError>

Returns tag labels matching prefix (case-insensitive) paired with usage counts, capped at limit. Used to feed the hashtag autocomplete popup in both the editor and the search box.

Source

pub async fn label_counts(&self) -> Result<Vec<(String, usize)>, VaultError>

Returns every distinct label in the vault paired with the number of notes carrying it. Labels are returned sorted alphabetically.

Source

pub async fn notes_with_label<S: AsRef<str>>( &self, name: S, ) -> Result<Vec<VaultPath>, VaultError>

Returns every note path that carries the given label. The label argument is lowercased before lookup, matching how labels are stored.

Source

pub async fn get_notes( &self, path: &VaultPath, recursive: bool, ) -> Result<Vec<(NoteEntryData, NoteContentData)>, VaultError>

Get notes under the given path. When recursive is false, only direct children are returned.

Source

pub async fn get_all_notes( &self, ) -> Result<Vec<(NoteEntryData, NoteContentData)>, VaultError>

Returns every note in the vault with its entry and content data.

Source

pub fn path_to_pathbuf(&self, path: &VaultPath) -> PathBuf

Resolves a vault path to its real OS filesystem location under the workspace root.

Source

pub async fn browse_vault( &self, options: VaultBrowseOptions, ) -> Result<(), VaultError>

Walks the vault per options, streaming each entry as a SearchResult through the channel set up by VaultBrowseOptionsBuilder::build. A recursive browse from the root doubles as a full index sync.

Source

pub fn get_directories( &self, path: &VaultPath, recursive: bool, ) -> Result<Vec<DirectoryDetails>, VaultError>

Returns all subdirectories under path. Non-recursive returns only the immediate children; recursive returns the full tree.

Converts a note’s raw Markdown into rendered Markdown and extracts all links.

  • WikiLinks ([[note]]) are converted to standard Markdown links.
  • Note links are resolved to vault-relative absolute paths.
  • Hashtags become Markdown links ([#tag](#tag)) and are added to the links list.
  • Image paths are resolved to absolute OS paths so renderers can load them directly. Relative image paths are resolved against the note’s location in the vault. External image URLs are kept as-is.

Returns all notes that contain a link pointing to path. Matches both absolute vault paths and bare filename links (wikilinks).

Source

pub async fn list_saved_searches(&self) -> Result<Vec<SavedSearch>, VaultError>

List the vault’s saved searches (see SavedSearch). Empty if none.

Source

pub async fn suggest_saved_searches_by_prefix( &self, prefix: &str, limit: usize, ) -> Result<Vec<SavedSearch>, VaultError>

Saved searches whose name starts with prefix (case-insensitive, ASCII folding to match Self::save_search/Self::delete_saved_search), in stored order, capped at limit. Feeds the ?-prefix autocomplete in the query input — mirrors Self::suggest_notes_by_prefix / Self::suggest_tags_by_prefix so prefix matching stays in core. Saved searches are file-backed (not indexed), so this reads the small TOML file; it is the single place to add caching if it ever gets hot.

Insert or replace a saved search by name (case-insensitive match, preserving the existing position on overwrite). Appends if new.

Delete a saved search by name (case-insensitive). No-op if absent.

Rename a saved search, preserving its position and query. No-op if absent.

Source

pub async fn create_note<S: AsRef<str>>( &self, path: &VaultPath, text: S, ) -> Result<(NoteEntryData, NoteContentData), VaultError>

Creates a new note at path with text, failing with VaultError::NoteExists if a note is already there. The create is exclusive (atomic O_EXCL), so it never clobbers an existing file. The new note is indexed before returning.

Source

pub async fn create_directory( &self, path: &VaultPath, ) -> Result<DirectoryEntryData, VaultError>

Creates a directory at path, failing with VaultError::DirectoryExists if one is already there.

Source

pub async fn append_to_note( &self, path: &VaultPath, text: &str, default: Option<String>, ) -> Result<(), VaultError>

Appends text to the note at path, creating it (with default content) when absent. The read and the write run under the per-note lock so concurrent appends to the same note can’t lose an update.

Source

pub async fn save_note<S: AsRef<str>>( &self, path: &VaultPath, text: S, ) -> Result<(NoteEntryData, NoteContentData), VaultError>

Writes text to the note at path, overwriting any existing content (backing it up first when backups are enabled), and re-indexes the note. Serialized per note via the per-note write lock.

Source

pub fn default_attachments_path(&self) -> VaultPath

Default attachments directory (e.g. /assets) inside the workspace.

Source

pub fn generate_attachment_path(&self, prefix: &str, ext: &str) -> VaultPath

Builds a candidate path for a new attachment under Self::default_attachments_path, using prefix and ext plus the current unix-nanosecond timestamp for uniqueness. Nanoseconds (rather than millis) make same-instant collisions vanishingly unlikely for human-driven actions like clipboard paste.

Does not check for collisions; callers that need stronger uniqueness guarantees should retry with Self::exists or use a different strategy.

Source

pub async fn save_attachment( &self, path: &VaultPath, bytes: &[u8], ) -> Result<(), VaultError>

Writes an attachment (raw bytes — e.g. an encoded PNG) to path under the workspace. Creates parent directories as needed. The attachment is not added to the notes index.

If the path looks like a specific note (has the note extension), search by name; otherwise treat it as a directory/path query that may return many results.

Source

pub async fn delete_note(&self, path: &VaultPath) -> Result<(), VaultError>

Deletes the note at path (backing it up first when backups are enabled). The index row is removed before the file, so the index never points at a missing file.

Source

pub async fn replace_in_note( &self, path: &VaultPath, pattern: &str, replacement: &str, all: bool, regex: bool, ) -> Result<usize, VaultError>

Replaces occurrences of pattern with replacement in the note at path, writing the result. See compute_replacement for the matching rules (literal vs regex, unique-unless-all, capture references). Returns the number of replacements made.

Source

pub async fn preview_replace( &self, path: &VaultPath, pattern: &str, replacement: &str, all: bool, regex: bool, ) -> Result<ReplacePreview, VaultError>

Dry-run of Self::replace_in_note: computes what the note would contain after the replacement without writing (and without taking the write lock — the result is advisory). Returns the same errors the real replace would (not found / not unique / invalid regex).

Source

pub async fn delete_directory(&self, path: &VaultPath) -> Result<(), VaultError>

Deletes the directory at path and its contents, removing the corresponding index rows first.

Source

pub async fn rename_note( &self, from: &VaultPath, to: &VaultPath, ) -> Result<(), VaultError>

Renames the note from to to, rewriting links to it (wikilinks, Markdown links, and the note’s own self-links) in every backlinking note so they keep pointing at the renamed note. Fails if to already exists. Source, destination, and all link victims are locked for the whole operation so a concurrent in-process write can’t interleave.

Source

pub async fn rename_directory( &self, from: &VaultPath, to: &VaultPath, ) -> Result<(), VaultError>

Renames the directory from to to, updating the index paths of all notes beneath it. Fails if to already exists.

Trait Implementations§

Source§

impl Clone for NoteVault

Source§

fn clone(&self) -> NoteVault

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for NoteVault

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for NoteVault

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more