feat: rework Electron desktop app to run standalone-first with optional two-way sync to a remote Termix server

This commit is contained in:
LukeGus
2026-07-21 01:27:03 -05:00
parent f44d09eef7
commit 08825c256d
77 changed files with 3658 additions and 929 deletions
@@ -1,4 +1,5 @@
import { and, eq, inArray } from "drizzle-orm";
import { randomUUID } from "crypto";
import { hostAccess, hosts } from "../db/schema.js";
import type { DatabaseContext } from "./database-context.js";
import { DataCrypto } from "../../utils/data-crypto.js";
@@ -22,7 +23,7 @@ export class HostRepository {
async create(host: NewHostRecord): Promise<HostRecord> {
const rows = await this.context.drizzle
.insert(hosts)
.values(host)
.values({ syncId: randomUUID(), ...host })
.returning();
await this.afterWrite();
return rows[0];
@@ -34,7 +35,11 @@ export class HostRepository {
): Promise<HostRecord> {
const userDataKey = DataCrypto.validateUserAccess(userId);
const tempId = host.id ?? Date.now();
const dataWithTempId = { ...host, id: tempId };
const dataWithTempId = {
syncId: randomUUID(),
...host,
id: tempId,
};
const encryptedHost = DataCrypto.encryptRecord(
"ssh_data",
dataWithTempId,
@@ -221,16 +226,19 @@ export class HostRepository {
return rows.length;
}
async deleteForUser(userId: string, hostId: number): Promise<boolean> {
async deleteForUser(
userId: string,
hostId: number,
): Promise<{ syncId: string | null } | null> {
await this.deleteAccessForHost(hostId);
const rows = await this.context.drizzle
.delete(hosts)
.where(and(eq(hosts.id, hostId), eq(hosts.userId, userId)))
.returning({ id: hosts.id });
.returning({ syncId: hosts.syncId });
await this.afterWrite();
return rows.length > 0;
return rows[0] ?? null;
}
async deleteByUserId(userId: string): Promise<number> {