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
version
property. - 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. Ifrecursive
is 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 aReadableStream
for 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.json
if 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.gitignore
file (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.,children
arrays from collections/folders,parentId
from 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
,children
arrays which are reconstructed during recursive loading).- Reading Info Files: The
readInfoFile
private method handles reading the JSON, parsing it, and triggering schema migration viamigrateInfoFile
if needed.
File System Interaction
- Uses Node.js
fs/promises
module for asynchronous file operations (e.g.,readFile
,writeFile
,mkdir
,rm
,rename
). - Uses
node:fs.createReadStream
for 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.