/// Abstract interface for reading/writing vault files on a git host. /// /// Both Gitea and GitHub expose a "repo contents" REST API that lets us /// read, write, and delete individual files without cloning the repo. /// This interface captures just the operations the vault needs. export interface GitHost { /// Read a single file from the repo, returning its raw bytes. readFile(path: string): Promise; /// Create or update a file in the repo with a commit message. writeFile(path: string, content: Uint8Array, message: string): Promise; /// Delete a file from the repo with a commit message. deleteFile(path: string, message: string): Promise; /// List file names in a directory (non-recursive). listDir(path: string): Promise; } /// Convert a Uint8Array to a base64 string (works in service worker context). export function uint8ArrayToBase64(bytes: Uint8Array): string { let binary = ''; for (let i = 0; i < bytes.length; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); } /// Convert a base64 string to a Uint8Array. export function base64ToUint8Array(base64: string): Uint8Array { const binary = atob(base64); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) { bytes[i] = binary.charCodeAt(i); } return bytes; } /// Factory function that returns the appropriate GitHost implementation. import { GiteaHost } from './gitea'; import { GitHubHost } from './github'; export function createGitHost( hostType: 'gitea' | 'github', hostUrl: string, repoPath: string, apiToken: string, ): GitHost { if (hostType === 'gitea') { return new GiteaHost(hostUrl, repoPath, apiToken); } return new GitHubHost(repoPath, apiToken); }