Browse Source

chore(linting): some linting problems fixed

sql-absurd-sql-further
Matthew Raymer 3 days ago
parent
commit
8edddb1a57
  1. 10
      src/libs/util.ts
  2. 227
      src/services/platforms/ElectronPlatformService.ts
  3. 26
      src/views/AccountViewView.vue

10
src/libs/util.ts

@ -646,29 +646,29 @@ export async function saveNewIdentity(
const secrets = await platformService.dbQuery(
`SELECT secretBase64 FROM secret`,
);
// If no secret exists, create one
let secretBase64: string;
if (!secrets?.values?.length || !secrets.values[0]?.length) {
// Generate a new secret
const randomBytes = crypto.getRandomValues(new Uint8Array(32));
secretBase64 = arrayBufferToBase64(randomBytes);
// Store the new secret
await platformService.dbExec(
`INSERT INTO secret (id, secretBase64) VALUES (1, ?)`,
[secretBase64]
[secretBase64],
);
} else {
secretBase64 = secrets.values[0][0] as string;
}
const secret = base64ToArrayBuffer(secretBase64);
const encryptedIdentity = await simpleEncrypt(identity, secret);
const encryptedMnemonic = await simpleEncrypt(mnemonic, secret);
const encryptedIdentityBase64 = arrayBufferToBase64(encryptedIdentity);
const encryptedMnemonicBase64 = arrayBufferToBase64(encryptedMnemonic);
await platformService.dbExec(
`INSERT INTO accounts (dateCreated, derivationPath, did, identityEncrBase64, mnemonicEncrBase64, publicKeyHex)
VALUES (?, ?, ?, ?, ?, ?)`,

227
src/services/platforms/ElectronPlatformService.ts

@ -93,13 +93,17 @@ export class ElectronPlatformService implements PlatformService {
private isConnectionOpen = false;
private operationQueue: Promise<unknown> = Promise.resolve();
private queueLock = false;
private connectionState: 'disconnected' | 'connecting' | 'connected' | 'error' = 'disconnected';
private connectionState:
| "disconnected"
| "connecting"
| "connected"
| "error" = "disconnected";
private connectionPromise: Promise<void> | null = null;
// SQLite initialization configuration
private static readonly SQLITE_CONFIG = {
INITIALIZATION: {
TIMEOUT_MS: 5000, // Increase timeout to 5 seconds
TIMEOUT_MS: 5000, // Increase timeout to 5 seconds
RETRY_ATTEMPTS: 3,
RETRY_DELAY_MS: 1000,
READY_CHECK_INTERVAL_MS: 100,
@ -124,18 +128,25 @@ export class ElectronPlatformService implements PlatformService {
}
// Check if SQLite is already available
const isAvailable = await window.electron.ipcRenderer.invoke("sqlite-is-available");
const isAvailable = await window.electron.ipcRenderer.invoke(
"sqlite-is-available",
);
if (!isAvailable) {
return false;
}
// Check if database is already open
const isOpen = await window.electron.ipcRenderer.invoke("sqlite-is-db-open", {
database: this.dbName,
});
const isOpen = await window.electron.ipcRenderer.invoke(
"sqlite-is-db-open",
{
database: this.dbName,
},
);
if (isOpen) {
logger.info("[ElectronPlatformService] SQLite is already ready and database is open");
logger.info(
"[ElectronPlatformService] SQLite is already ready and database is open",
);
sqliteInitState.isReady = true;
sqliteInitState.isInitializing = false;
sqliteInitState.lastReadyCheck = Date.now();
@ -144,7 +155,10 @@ export class ElectronPlatformService implements PlatformService {
return false;
} catch (error) {
logger.warn("[ElectronPlatformService] Error checking existing readiness:", error);
logger.warn(
"[ElectronPlatformService] Error checking existing readiness:",
error,
);
return false;
}
};
@ -161,8 +175,14 @@ export class ElectronPlatformService implements PlatformService {
// If someone else is initializing, wait for them
if (sqliteInitState.isInitializing) {
logger.info("[ElectronPlatformService] Another initialization in progress, waiting...");
setTimeout(attemptInitialization, ElectronPlatformService.SQLITE_CONFIG.INITIALIZATION.READY_CHECK_INTERVAL_MS);
logger.info(
"[ElectronPlatformService] Another initialization in progress, waiting...",
);
setTimeout(
attemptInitialization,
ElectronPlatformService.SQLITE_CONFIG.INITIALIZATION
.READY_CHECK_INTERVAL_MS,
);
return;
}
@ -171,7 +191,9 @@ export class ElectronPlatformService implements PlatformService {
// Verify Electron API exposure first
await verifyElectronAPI();
logger.info("[ElectronPlatformService] Electron API verification successful");
logger.info(
"[ElectronPlatformService] Electron API verification successful",
);
if (!window.electron?.ipcRenderer) {
logger.warn("[ElectronPlatformService] IPC renderer not available");
@ -182,12 +204,16 @@ export class ElectronPlatformService implements PlatformService {
// Set up ready signal handler BEFORE setting timeout
window.electron.ipcRenderer.once("sqlite-ready", async () => {
cleanup();
logger.info("[ElectronPlatformService] Received SQLite ready signal");
logger.info(
"[ElectronPlatformService] Received SQLite ready signal",
);
try {
// Test SQLite operations after receiving ready signal
await testSQLiteOperations();
logger.info("[ElectronPlatformService] SQLite operations test successful");
logger.info(
"[ElectronPlatformService] SQLite operations test successful",
);
this.isInitialized = true;
sqliteInitState.isReady = true;
@ -197,43 +223,67 @@ export class ElectronPlatformService implements PlatformService {
} catch (error) {
sqliteInitState.error = error as Error;
sqliteInitState.isInitializing = false;
logger.error("[ElectronPlatformService] SQLite operations test failed:", error);
logger.error(
"[ElectronPlatformService] SQLite operations test failed:",
error,
);
reject(error);
}
});
// Set up error handler
window.electron.ipcRenderer.once("database-status", (...args: unknown[]) => {
cleanup();
const status = args[0] as { status: string; error?: string };
if (status.status === "error") {
this.dbFatalError = true;
sqliteInitState.error = new Error(status.error || "Database initialization failed");
sqliteInitState.isInitializing = false;
reject(sqliteInitState.error);
}
});
window.electron.ipcRenderer.once(
"database-status",
(...args: unknown[]) => {
cleanup();
const status = args[0] as { status: string; error?: string };
if (status.status === "error") {
this.dbFatalError = true;
sqliteInitState.error = new Error(
status.error || "Database initialization failed",
);
sqliteInitState.isInitializing = false;
reject(sqliteInitState.error);
}
},
);
// Set timeout for this attempt AFTER setting up handlers
this.initializationTimeout = setTimeout(() => {
if (retryCount < ElectronPlatformService.SQLITE_CONFIG.INITIALIZATION.RETRY_ATTEMPTS) {
if (
retryCount <
ElectronPlatformService.SQLITE_CONFIG.INITIALIZATION
.RETRY_ATTEMPTS
) {
retryCount++;
logger.warn(`[ElectronPlatformService] SQLite initialization attempt ${retryCount} timed out, retrying...`);
setTimeout(attemptInitialization, ElectronPlatformService.SQLITE_CONFIG.INITIALIZATION.RETRY_DELAY_MS);
logger.warn(
`[ElectronPlatformService] SQLite initialization attempt ${retryCount} timed out, retrying...`,
);
setTimeout(
attemptInitialization,
ElectronPlatformService.SQLITE_CONFIG.INITIALIZATION
.RETRY_DELAY_MS,
);
} else {
cleanup();
sqliteInitState.isInitializing = false;
sqliteInitState.error = new Error("SQLite initialization timeout after all retries");
logger.error("[ElectronPlatformService] SQLite initialization failed after all retries");
sqliteInitState.error = new Error(
"SQLite initialization timeout after all retries",
);
logger.error(
"[ElectronPlatformService] SQLite initialization failed after all retries",
);
reject(sqliteInitState.error);
}
}, ElectronPlatformService.SQLITE_CONFIG.INITIALIZATION.TIMEOUT_MS);
} catch (error) {
cleanup();
sqliteInitState.error = error as Error;
sqliteInitState.isInitializing = false;
logger.error("[ElectronPlatformService] Initialization failed:", error);
logger.error(
"[ElectronPlatformService] Initialization failed:",
error,
);
reject(error);
}
};
@ -254,30 +304,30 @@ export class ElectronPlatformService implements PlatformService {
// Use IPC bridge with specific methods
this.sqlite = {
createConnection: async (options) => {
await window.electron.ipcRenderer.invoke('sqlite-create-connection', {
await window.electron.ipcRenderer.invoke("sqlite-create-connection", {
...options,
database: this.dbName
database: this.dbName,
});
},
query: async (options) => {
return await window.electron.ipcRenderer.invoke('sqlite-query', {
return await window.electron.ipcRenderer.invoke("sqlite-query", {
...options,
database: this.dbName
database: this.dbName,
});
},
run: async (options) => {
return await window.electron.ipcRenderer.invoke('sqlite-run', {
return await window.electron.ipcRenderer.invoke("sqlite-run", {
...options,
database: this.dbName
database: this.dbName,
});
},
execute: async (options) => {
await window.electron.ipcRenderer.invoke('sqlite-execute', {
await window.electron.ipcRenderer.invoke("sqlite-execute", {
...options,
database: this.dbName,
statements: [{ statement: options.statements }]
statements: [{ statement: options.statements }],
});
}
},
} as SQLiteOperations;
// Create the connection (idempotent)
@ -537,7 +587,7 @@ export class ElectronPlatformService implements PlatformService {
try {
// Acquire lock
while (this.queueLock) {
await new Promise(resolve => setTimeout(resolve, 50));
await new Promise((resolve) => setTimeout(resolve, 50));
}
this.queueLock = true;
@ -562,20 +612,20 @@ export class ElectronPlatformService implements PlatformService {
}
// If we're already connected, return immediately
if (this.connectionState === 'connected') {
if (this.connectionState === "connected") {
return Promise.resolve();
}
// Create new connection promise
this.connectionPromise = (async () => {
try {
this.connectionState = 'connecting';
this.connectionState = "connecting";
// Wait for any existing operations
await this.operationQueue;
// Create connection
await window.electron!.ipcRenderer.invoke('sqlite-create-connection', {
await window.electron!.ipcRenderer.invoke("sqlite-create-connection", {
database: this.dbName,
encrypted: false,
mode: "no-encryption",
@ -583,23 +633,26 @@ export class ElectronPlatformService implements PlatformService {
logger.debug("[ElectronPlatformService] Database connection created");
// Open database
await window.electron!.ipcRenderer.invoke('sqlite-open', {
database: this.dbName
await window.electron!.ipcRenderer.invoke("sqlite-open", {
database: this.dbName,
});
logger.debug("[ElectronPlatformService] Database opened");
// Verify database is open
const isOpen = await window.electron!.ipcRenderer.invoke('sqlite-is-db-open', {
database: this.dbName
});
const isOpen = await window.electron!.ipcRenderer.invoke(
"sqlite-is-db-open",
{
database: this.dbName,
},
);
if (!isOpen) {
throw new Error('[ElectronPlatformService] Database failed to open');
throw new Error("[ElectronPlatformService] Database failed to open");
}
this.connectionState = 'connected';
this.connectionState = "connected";
this.isConnectionOpen = true;
} catch (error) {
this.connectionState = 'error';
this.connectionState = "error";
this.connectionPromise = null;
throw error;
}
@ -609,28 +662,31 @@ export class ElectronPlatformService implements PlatformService {
}
private async releaseConnection(): Promise<void> {
if (this.connectionState !== 'connected') {
if (this.connectionState !== "connected") {
return;
}
try {
// Close database
await window.electron!.ipcRenderer.invoke('sqlite-close', {
database: this.dbName
await window.electron!.ipcRenderer.invoke("sqlite-close", {
database: this.dbName,
});
logger.debug("[ElectronPlatformService] Database closed");
// Close connection
await window.electron!.ipcRenderer.invoke('sqlite-close-connection', {
database: this.dbName
await window.electron!.ipcRenderer.invoke("sqlite-close-connection", {
database: this.dbName,
});
logger.debug("[ElectronPlatformService] Database connection closed");
this.connectionState = 'disconnected';
this.connectionState = "disconnected";
this.isConnectionOpen = false;
} catch (error) {
logger.error("[ElectronPlatformService] Failed to close database:", error);
this.connectionState = 'error';
logger.error(
"[ElectronPlatformService] Failed to close database:",
error,
);
this.connectionState = "error";
} finally {
this.connectionPromise = null;
}
@ -650,7 +706,9 @@ export class ElectronPlatformService implements PlatformService {
params: unknown[] = [],
): Promise<QueryExecResult<T>> {
if (this.dbFatalError) {
throw new Error("Database is in a fatal error state. Please restart the app.");
throw new Error(
"Database is in a fatal error state. Please restart the app.",
);
}
return this.enqueueOperation(async () => {
@ -659,23 +717,33 @@ export class ElectronPlatformService implements PlatformService {
await this.getConnection();
// Execute query
const result = await window.electron!.ipcRenderer.invoke('sqlite-query', {
database: this.dbName,
statement: sql,
values: params
}) as SQLiteQueryResult;
logger.debug("[ElectronPlatformService] [dbQuery] Query executed successfully");
const result = (await window.electron!.ipcRenderer.invoke(
"sqlite-query",
{
database: this.dbName,
statement: sql,
values: params,
},
)) as SQLiteQueryResult;
logger.debug(
"[ElectronPlatformService] [dbQuery] Query executed successfully",
);
// Process results
const columns = result.values?.[0] ? Object.keys(result.values[0]) : [];
const processedResult = {
columns,
values: (result.values || []).map((row: Record<string, unknown>) => row as T)
values: (result.values || []).map(
(row: Record<string, unknown>) => row as T,
),
};
return processedResult;
} catch (error) {
logger.error("[ElectronPlatformService] [dbQuery] Query failed:", error);
logger.error(
"[ElectronPlatformService] [dbQuery] Query failed:",
error,
);
throw error;
} finally {
// Release connection after query
@ -692,7 +760,9 @@ export class ElectronPlatformService implements PlatformService {
params?: unknown[],
): Promise<{ changes: number; lastId?: number }> {
if (this.dbFatalError) {
throw new Error("Database is in a fatal error state. Please restart the app.");
throw new Error(
"Database is in a fatal error state. Please restart the app.",
);
}
return this.enqueueOperation(async () => {
@ -701,12 +771,17 @@ export class ElectronPlatformService implements PlatformService {
await this.getConnection();
// Execute query
const result = await window.electron!.ipcRenderer.invoke('sqlite-run', {
database: this.dbName,
statement: sql,
values: params
}) as SQLiteQueryResult;
logger.debug("[ElectronPlatformService] [dbExec] Query executed successfully");
const result = (await window.electron!.ipcRenderer.invoke(
"sqlite-run",
{
database: this.dbName,
statement: sql,
values: params,
},
)) as SQLiteQueryResult;
logger.debug(
"[ElectronPlatformService] [dbExec] Query executed successfully",
);
return {
changes: result.changes?.changes || 0,

26
src/views/AccountViewView.vue

@ -1889,7 +1889,7 @@ export default class AccountViewView extends Vue {
logger.debug("[AccountViewView] Starting API server update", {
current: this.apiServer,
new: this.apiServerInput,
component: 'AccountViewView'
component: "AccountViewView",
});
try {
@ -1909,29 +1909,33 @@ export default class AccountViewView extends Vue {
}
this.apiServer = this.apiServerInput;
logger.debug("[AccountViewView] Local state updated", { apiServer: this.apiServer });
logger.debug("[AccountViewView] Local state updated", {
apiServer: this.apiServer,
});
// Verify the update
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
logger.debug("[AccountViewView] Settings verification", {
retrieved: settings.apiServer,
expected: this.apiServerInput,
match: settings.apiServer === this.apiServerInput
match: settings.apiServer === this.apiServerInput,
});
// Show success notification
this.$notify({
group: "alert",
type: "success",
title: "API Server Updated",
text: "API server settings saved successfully.",
}, 3000);
this.$notify(
{
group: "alert",
type: "success",
title: "API Server Updated",
text: "API server settings saved successfully.",
},
3000,
);
} catch (error) {
logger.error("[AccountViewView] API server update failed", {
error,
current: this.apiServer,
attempted: this.apiServerInput
attempted: this.apiServerInput,
});
this.$notify(
{

Loading…
Cancel
Save