chore(linting): some linting problems fixed
This commit is contained in:
@@ -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 (?, ?, ?, ?, ?, ?)`,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user