Persistence Service
Location: src/main/persistence/service/persistence-service.ts
The PersistenceService is a cornerstone of Trufos’s main process, responsible for all interactions with the file system concerning the storage and retrieval of collections, folders, and requests.
Core Responsibilities
- Data Storage Model: - Each Collection, Folder, and Request is generally represented by a directory on the disk.
- Metadata for these objects is stored in a JSON file within their respective directories (e.g., collection.json,folder.json,request.json).
- Request bodies (text-based) are stored in separate files (e.g., request-body.txt).
 
- CRUD Operations: - Creating new collections, folders, and requests on disk.
- Reading object metadata and content from files.
- Updating object metadata and content.
- Deleting objects and their associated directories/files.
 
- Directory and File Naming: - Derives directory names from sanitized object titles (lowercase, hyphenated, special characters removed via sanitizeTitle).
- Handles potential name collisions by appending sequential numbers (e.g., my-folder,my-folder-2).
 
- Derives directory names from sanitized object titles (lowercase, hyphenated, special characters removed via 
- Draft Management: - Supports a “draft” state for requests. Draft metadata is saved in files prefixed with ~(e.g.,~request.json,~request-body.txt).
- saveChanges(request): Promotes draft files to become the main files.
- discardChanges(request): Deletes draft files, reverting to the last non-draft state.
 
- Supports a “draft” state for requests. Draft metadata is saved in files prefixed with 
- Schema Migration: - When loading info files, checks their versionproperty.
- If an older version is detected, it uses migrateInfoFile(fromsrc/main/persistence/service/info-files/migrators.ts) to upgrade the data structure to the latest schema before parsing.
 
- When loading info files, checks their 
- Path Management: - Maintains an internal idToPathMap(aMap<string, string>) to associate object IDs with their directory paths. This is crucial because directory names can change if an object’s title changes.
- getOrCreateDirPath(object): Retrieves the path for an object or generates a new, unique path if it’s a new object.
 
- Maintains an internal 
- Default Collection: - createDefaultCollectionIfNotExists(): Ensures that a default collection (defined in- src/main/persistence/service/default-collection.ts) is created for new users in the application’s user data directory.
 
Key Methods
- Loading Data: - loadCollection(dirPath, recursive?): Loads collection metadata. If- recursiveis true (default), it also loads all child folders and requests by traversing the directory structure.
- loadFolder(parentId, dirPath): Loads folder metadata and recursively its children.
- loadRequest(parentId, dirPath): Loads request metadata, checking for draft versions.
- loadTextBodyOfRequest(request, encoding?): Returns a- ReadableStreamfor a request’s text body (draft or main).
 
- Saving Data: - saveCollectionRecursive(collection): Saves an entire collection tree to disk.
- saveCollection(collection): Saves only the collection’s- collection.json.
- saveFolder(folder): Saves the folder’s- folder.json.
- saveRequest(request, textBody?): Saves the request’s- request.json(and- ~request.jsonif draft) and optionally its text body file.
 
- Modifying Structure: - rename(object, newTitle): Renames an object and its corresponding directory. Updates- idToPathMap.
- delete(object): Deletes an object’s directory and all its contents recursively. Updates- idToPathMap.
- moveChild(child, oldParent, newParent): Moves a child’s directory from one parent’s directory to another.
 
- Creating Collections: - createCollection(dirPath, title): Creates a new collection directory,- collection.json, and a- .gitignorefile (to ignore draft files).
 
Info File Handling
- toInfoFile(object)(- src/main/persistence/service/info-files/latest.ts): Converts an in-memory Trufos object (Collection, Folder, Request) into a plain JSON object suitable for storing in an info file. It omits properties not meant for persistence (e.g.,- childrenarrays from collections/folders,- parentIdfrom requests).
- from<Type>InfoFile(...)functions (- src/main/persistence/service/info-files/latest.ts): Convert plain JSON objects read from info files back into typed Trufos objects, re-adding necessary runtime properties (like- type,- parentId,- childrenarrays which are reconstructed during recursive loading).
- Reading Info Files: The readInfoFileprivate method handles reading the JSON, parsing it, and triggering schema migration viamigrateInfoFileif needed.
File System Interaction
- Uses Node.js fs/promisesmodule for asynchronous file operations (e.g.,readFile,writeFile,mkdir,rm,rename).
- Uses node:fs.createReadStreamfor streaming file content (e.g., request bodies).
- Utility exists(filePath)(fromsrc/main/util/fs-util.ts) checks for file/directory existence.
The PersistenceService is central to Trufos’s ability to manage user data persistently and in a way that is somewhat human-readable and version-control friendly.