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 insrc/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. Ifrecursiveis 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 aReadableStreamfor 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’scollection.json.saveFolder(folder): Saves the folder’sfolder.json.saveRequest(request, textBody?): Saves the request’srequest.json(and~request.jsonif draft) and optionally its text body file.
- Modifying Structure:
rename(object, newTitle): Renames an object and its corresponding directory. UpdatesidToPathMap.delete(object): Deletes an object’s directory and all its contents recursively. UpdatesidToPathMap.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 (liketype,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.