forked from trent_larson/crowd-funder-for-time-pwa
fix linting
This commit is contained in:
@@ -26,10 +26,19 @@ import "dexie-export-import";
|
||||
import { PlatformServiceFactory } from "./PlatformServiceFactory";
|
||||
import { db, accountsDBPromise } from "../db/index";
|
||||
import { Contact, ContactMethod } from "../db/tables/contacts";
|
||||
import { Settings, MASTER_SETTINGS_KEY, BoundingBox } from "../db/tables/settings";
|
||||
import {
|
||||
Settings,
|
||||
MASTER_SETTINGS_KEY,
|
||||
BoundingBox,
|
||||
} from "../db/tables/settings";
|
||||
import { Account } from "../db/tables/accounts";
|
||||
import { logger } from "../utils/logger";
|
||||
import { mapColumnsToValues, parseJsonField, generateUpdateStatement, generateInsertStatement } from "../db/databaseUtil";
|
||||
import {
|
||||
mapColumnsToValues,
|
||||
parseJsonField,
|
||||
generateUpdateStatement,
|
||||
generateInsertStatement,
|
||||
} from "../db/databaseUtil";
|
||||
import { importFromMnemonic } from "../libs/util";
|
||||
|
||||
/**
|
||||
@@ -186,12 +195,18 @@ export async function getSqliteContacts(): Promise<Contact[]> {
|
||||
|
||||
let contacts: Contact[] = [];
|
||||
if (result?.values?.length) {
|
||||
const preContacts = mapColumnsToValues(result.columns, result.values) as unknown as Contact[];
|
||||
const preContacts = mapColumnsToValues(
|
||||
result.columns,
|
||||
result.values,
|
||||
) as unknown as Contact[];
|
||||
// This is redundant since absurd-sql auto-parses JSON strings to objects.
|
||||
// But we started it, and it should be known everywhere, so we're keeping it.
|
||||
contacts = preContacts.map((contact) => {
|
||||
if (contact.contactMethods) {
|
||||
contact.contactMethods = parseJsonField(contact.contactMethods, []) as ContactMethod[];
|
||||
contact.contactMethods = parseJsonField(
|
||||
contact.contactMethods,
|
||||
[],
|
||||
) as ContactMethod[];
|
||||
}
|
||||
return contact;
|
||||
});
|
||||
@@ -212,7 +227,7 @@ export async function getSqliteContacts(): Promise<Contact[]> {
|
||||
*
|
||||
* This function connects to the Dexie database and retrieves all settings
|
||||
* records.
|
||||
*
|
||||
*
|
||||
* Settings include both master settings (id=1) and account-specific settings
|
||||
* that override the master settings for particular user accounts.
|
||||
*
|
||||
@@ -275,16 +290,21 @@ export async function getSqliteSettings(): Promise<Settings[]> {
|
||||
|
||||
let settings: Settings[] = [];
|
||||
if (result?.values?.length) {
|
||||
const presettings =
|
||||
mapColumnsToValues(result.columns, result.values) as Settings[];
|
||||
const presettings = mapColumnsToValues(
|
||||
result.columns,
|
||||
result.values,
|
||||
) as Settings[];
|
||||
// This is redundant since absurd-sql auto-parses JSON strings to objects.
|
||||
// But we started it, and it should be known everywhere, so we're keeping it.
|
||||
settings = presettings.map((setting) => {
|
||||
if (setting.searchBoxes) {
|
||||
setting.searchBoxes = parseJsonField(setting.searchBoxes, []) as Array<{ name: string, bbox: BoundingBox }>;
|
||||
setting.searchBoxes = parseJsonField(
|
||||
setting.searchBoxes,
|
||||
[],
|
||||
) as Array<{ name: string; bbox: BoundingBox }>;
|
||||
}
|
||||
return setting;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
logger.info(
|
||||
@@ -557,7 +577,9 @@ function compareSettings(
|
||||
|
||||
// Find settings that exist in Dexie but not in SQLite
|
||||
for (const dexieSetting of dexieSettings) {
|
||||
const sqliteSetting = sqliteSettings.find((s) => s.accountDid == dexieSetting.accountDid);
|
||||
const sqliteSetting = sqliteSettings.find(
|
||||
(s) => s.accountDid == dexieSetting.accountDid,
|
||||
);
|
||||
if (!sqliteSetting) {
|
||||
added.push(dexieSetting);
|
||||
} else if (!settingsEqual(dexieSetting, sqliteSetting)) {
|
||||
@@ -569,7 +591,9 @@ function compareSettings(
|
||||
|
||||
// Find settings that exist in SQLite but not in Dexie
|
||||
for (const sqliteSetting of sqliteSettings) {
|
||||
const dexieSetting = dexieSettings.find((s) => s.accountDid == sqliteSetting.accountDid);
|
||||
const dexieSetting = dexieSettings.find(
|
||||
(s) => s.accountDid == sqliteSetting.accountDid,
|
||||
);
|
||||
if (!dexieSetting) {
|
||||
missing.push(sqliteSetting);
|
||||
}
|
||||
@@ -654,22 +678,29 @@ function compareAccounts(dexieAccounts: Account[], sqliteDids: string[]) {
|
||||
* ```
|
||||
*/
|
||||
function contactsEqual(contact1: Contact, contact2: Contact): boolean {
|
||||
const ifEmpty = (arg: any, def: any) => !!arg ? arg : def;
|
||||
const ifEmpty = (arg: any, def: any) => (arg ? arg : def);
|
||||
const contact1Methods =
|
||||
contact1.contactMethods && Array.isArray(contact1.contactMethods) && contact1.contactMethods.length > 0
|
||||
? JSON.stringify(contact1.contactMethods)
|
||||
: "[]";
|
||||
contact1.contactMethods &&
|
||||
Array.isArray(contact1.contactMethods) &&
|
||||
contact1.contactMethods.length > 0
|
||||
? JSON.stringify(contact1.contactMethods)
|
||||
: "[]";
|
||||
const contact2Methods =
|
||||
contact2.contactMethods && Array.isArray(contact2.contactMethods) && contact2.contactMethods.length > 0
|
||||
? JSON.stringify(contact2.contactMethods)
|
||||
: "[]";
|
||||
contact2.contactMethods &&
|
||||
Array.isArray(contact2.contactMethods) &&
|
||||
contact2.contactMethods.length > 0
|
||||
? JSON.stringify(contact2.contactMethods)
|
||||
: "[]";
|
||||
return (
|
||||
ifEmpty(contact1.did, "") == ifEmpty(contact2.did, "") &&
|
||||
ifEmpty(contact1.name, "") == ifEmpty(contact2.name, "") &&
|
||||
ifEmpty(contact1.notes, "") == ifEmpty(contact2.notes, "") &&
|
||||
ifEmpty(contact1.profileImageUrl, "") == ifEmpty(contact2.profileImageUrl, "") &&
|
||||
ifEmpty(contact1.publicKeyBase64, "") == ifEmpty(contact2.publicKeyBase64, "") &&
|
||||
ifEmpty(contact1.nextPubKeyHashB64, "") == ifEmpty(contact2.nextPubKeyHashB64, "") &&
|
||||
ifEmpty(contact1.profileImageUrl, "") ==
|
||||
ifEmpty(contact2.profileImageUrl, "") &&
|
||||
ifEmpty(contact1.publicKeyBase64, "") ==
|
||||
ifEmpty(contact2.publicKeyBase64, "") &&
|
||||
ifEmpty(contact1.nextPubKeyHashB64, "") ==
|
||||
ifEmpty(contact2.nextPubKeyHashB64, "") &&
|
||||
!!contact1.seesMe == !!contact2.seesMe &&
|
||||
!!contact1.registered == !!contact2.registered &&
|
||||
contact1Methods == contact2Methods
|
||||
@@ -762,18 +793,21 @@ function settingsEqual(settings1: Settings, settings2: Settings): boolean {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
function accountsEqual(account1: Account, account2: Account): boolean {
|
||||
return (
|
||||
account1.id === account2.id &&
|
||||
account1.dateCreated === account2.dateCreated &&
|
||||
account1.derivationPath === account2.derivationPath &&
|
||||
account1.did === account2.did &&
|
||||
account1.identity === account2.identity &&
|
||||
account1.mnemonic === account2.mnemonic &&
|
||||
account1.passkeyCredIdHex === account2.passkeyCredIdHex &&
|
||||
account1.publicKeyHex === account2.publicKeyHex
|
||||
);
|
||||
}
|
||||
//
|
||||
// unused
|
||||
//
|
||||
// function accountsEqual(account1: Account, account2: Account): boolean {
|
||||
// return (
|
||||
// account1.id === account2.id &&
|
||||
// account1.dateCreated === account2.dateCreated &&
|
||||
// account1.derivationPath === account2.derivationPath &&
|
||||
// account1.did === account2.did &&
|
||||
// account1.identity === account2.identity &&
|
||||
// account1.mnemonic === account2.mnemonic &&
|
||||
// account1.passkeyCredIdHex === account2.passkeyCredIdHex &&
|
||||
// account1.publicKeyHex === account2.publicKeyHex
|
||||
// );
|
||||
// }
|
||||
|
||||
/**
|
||||
* Generates YAML-formatted comparison data
|
||||
@@ -801,58 +835,64 @@ export function generateComparisonYaml(comparison: DataComparison): string {
|
||||
const yaml = {
|
||||
summary: {
|
||||
dexieContacts: comparison.dexieContacts.length,
|
||||
sqliteContacts: comparison.sqliteContacts.filter(c => c.did).length,
|
||||
sqliteContacts: comparison.sqliteContacts.filter((c) => c.did).length,
|
||||
dexieSettings: comparison.dexieSettings.length,
|
||||
sqliteSettings: comparison.sqliteSettings.filter(s => s.accountDid || s.activeDid).length,
|
||||
sqliteSettings: comparison.sqliteSettings.filter(
|
||||
(s) => s.accountDid || s.activeDid,
|
||||
).length,
|
||||
dexieAccounts: comparison.dexieAccounts.length,
|
||||
sqliteAccounts: comparison.sqliteAccounts.filter(a => a).length,
|
||||
sqliteAccounts: comparison.sqliteAccounts.filter((a) => a).length,
|
||||
},
|
||||
differences: {
|
||||
contacts: {
|
||||
added: comparison.differences.contacts.added.length,
|
||||
modified: comparison.differences.contacts.modified.length,
|
||||
unmodified: comparison.differences.contacts.unmodified.length,
|
||||
missing: comparison.differences.contacts.missing.filter(c => c.did).length,
|
||||
missing: comparison.differences.contacts.missing.filter((c) => c.did)
|
||||
.length,
|
||||
},
|
||||
settings: {
|
||||
added: comparison.differences.settings.added.length,
|
||||
modified: comparison.differences.settings.modified.length,
|
||||
unmodified: comparison.differences.settings.unmodified.length,
|
||||
missing: comparison.differences.settings.missing.filter(s => s.accountDid || s.activeDid).length,
|
||||
missing: comparison.differences.settings.missing.filter(
|
||||
(s) => s.accountDid || s.activeDid,
|
||||
).length,
|
||||
},
|
||||
accounts: {
|
||||
added: comparison.differences.accounts.added.length,
|
||||
unmodified: comparison.differences.accounts.unmodified.length,
|
||||
missing: comparison.differences.accounts.missing.filter(a => a).length,
|
||||
missing: comparison.differences.accounts.missing.filter((a) => a)
|
||||
.length,
|
||||
},
|
||||
},
|
||||
details: {
|
||||
contacts: {
|
||||
dexie: comparison.dexieContacts.map((c) => ({
|
||||
did: c.did,
|
||||
name: c.name || '<empty>',
|
||||
name: c.name || "<empty>",
|
||||
contactMethods: (c.contactMethods || []).length,
|
||||
})),
|
||||
sqlite: comparison.sqliteContacts
|
||||
.filter(c => c.did)
|
||||
.filter((c) => c.did)
|
||||
.map((c) => ({
|
||||
did: c.did,
|
||||
name: c.name || '<empty>',
|
||||
name: c.name || "<empty>",
|
||||
contactMethods: (c.contactMethods || []).length,
|
||||
})),
|
||||
},
|
||||
settings: {
|
||||
dexie: comparison.dexieSettings.map((s) => ({
|
||||
id: s.id,
|
||||
type: s.id === MASTER_SETTINGS_KEY ? 'master' : 'account',
|
||||
type: s.id === MASTER_SETTINGS_KEY ? "master" : "account",
|
||||
did: s.activeDid || s.accountDid,
|
||||
isRegistered: s.isRegistered || false,
|
||||
})),
|
||||
sqlite: comparison.sqliteSettings
|
||||
.filter(s => s.accountDid || s.activeDid)
|
||||
.filter((s) => s.accountDid || s.activeDid)
|
||||
.map((s) => ({
|
||||
id: s.id,
|
||||
type: s.id === MASTER_SETTINGS_KEY ? 'master' : 'account',
|
||||
type: s.id === MASTER_SETTINGS_KEY ? "master" : "account",
|
||||
did: s.activeDid || s.accountDid,
|
||||
isRegistered: s.isRegistered || false,
|
||||
})),
|
||||
@@ -1039,20 +1079,22 @@ export async function migrateSettings(): Promise<MigrationResult> {
|
||||
dexieSettings: dexieSettings.length,
|
||||
});
|
||||
const platformService = PlatformServiceFactory.getInstance();
|
||||
|
||||
|
||||
// Create an array of promises for all settings migrations
|
||||
const migrationPromises = dexieSettings.map(async (setting) => {
|
||||
logger.info("[MigrationService] Starting to migrate settings", setting);
|
||||
let sqliteSettingRaw: { columns: string[], values: unknown[][] } | undefined;
|
||||
let sqliteSettingRaw:
|
||||
| { columns: string[]; values: unknown[][] }
|
||||
| undefined;
|
||||
if (!setting.accountDid) {
|
||||
sqliteSettingRaw = await platformService.dbQuery(
|
||||
"SELECT * FROM settings WHERE accountDid is null"
|
||||
"SELECT * FROM settings WHERE accountDid is null",
|
||||
);
|
||||
} else {
|
||||
sqliteSettingRaw = await platformService.dbQuery(
|
||||
"SELECT * FROM settings WHERE accountDid = ?",
|
||||
[setting.accountDid]
|
||||
)
|
||||
[setting.accountDid],
|
||||
);
|
||||
}
|
||||
logger.info("[MigrationService] Migrating one set of settings:", {
|
||||
setting,
|
||||
@@ -1060,9 +1102,11 @@ export async function migrateSettings(): Promise<MigrationResult> {
|
||||
});
|
||||
if (sqliteSettingRaw?.values?.length) {
|
||||
// should cover the master settings, were accountDid is null
|
||||
const sqliteSettings = mapColumnsToValues(sqliteSettingRaw.columns, sqliteSettingRaw.values) as unknown as Settings[];
|
||||
const sqliteSettings = mapColumnsToValues(
|
||||
sqliteSettingRaw.columns,
|
||||
sqliteSettingRaw.values,
|
||||
) as unknown as Settings[];
|
||||
const sqliteSetting = sqliteSettings[0];
|
||||
console.log('sqliteSetting', sqliteSetting)
|
||||
let conditional: string;
|
||||
let preparams: unknown[];
|
||||
if (!setting.accountDid) {
|
||||
@@ -1076,16 +1120,16 @@ export async function migrateSettings(): Promise<MigrationResult> {
|
||||
sqliteSetting as unknown as Record<string, unknown>,
|
||||
"settings",
|
||||
conditional,
|
||||
preparams
|
||||
preparams,
|
||||
);
|
||||
await platformService.dbExec(sql, params)
|
||||
await platformService.dbExec(sql, params);
|
||||
result.settingsMigrated++;
|
||||
} else {
|
||||
// insert new setting
|
||||
delete setting.activeDid; // ensure we don't set the activeDid (since master settings are an update and don't hit this case)
|
||||
const { sql, params } = generateInsertStatement(
|
||||
setting as unknown as Record<string, unknown>,
|
||||
"settings"
|
||||
"settings",
|
||||
);
|
||||
await platformService.dbExec(sql, params);
|
||||
result.settingsMigrated++;
|
||||
@@ -1094,12 +1138,19 @@ export async function migrateSettings(): Promise<MigrationResult> {
|
||||
|
||||
// Wait for all migrations to complete
|
||||
const updatedSettings = await Promise.all(migrationPromises);
|
||||
|
||||
logger.info("[MigrationService] Finished migrating settings", updatedSettings, result);
|
||||
|
||||
logger.info(
|
||||
"[MigrationService] Finished migrating settings",
|
||||
updatedSettings,
|
||||
result,
|
||||
);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
logger.error("[MigrationService] Complete settings migration failed:", error);
|
||||
logger.error(
|
||||
"[MigrationService] Complete settings migration failed:",
|
||||
error,
|
||||
);
|
||||
const errorMessage = `Settings migration failed: ${error}`;
|
||||
result.errors.push(errorMessage);
|
||||
result.success = false;
|
||||
@@ -1158,12 +1209,17 @@ export async function migrateAccounts(): Promise<MigrationResult> {
|
||||
|
||||
// Group accounts by DID and keep only the most recent one
|
||||
const accountsByDid = new Map<string, Account>();
|
||||
dexieAccounts.forEach(account => {
|
||||
dexieAccounts.forEach((account) => {
|
||||
const existingAccount = accountsByDid.get(account.did);
|
||||
if (!existingAccount || new Date(account.dateCreated) > new Date(existingAccount.dateCreated)) {
|
||||
if (
|
||||
!existingAccount ||
|
||||
new Date(account.dateCreated) > new Date(existingAccount.dateCreated)
|
||||
) {
|
||||
accountsByDid.set(account.did, account);
|
||||
if (existingAccount) {
|
||||
result.warnings.push(`Found duplicate account for DID ${account.did}, keeping most recent`);
|
||||
result.warnings.push(
|
||||
`Found duplicate account for DID ${account.did}, keeping most recent`,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1174,30 +1230,34 @@ export async function migrateAccounts(): Promise<MigrationResult> {
|
||||
// Check if account already exists
|
||||
const existingResult = await platformService.dbQuery(
|
||||
"SELECT did FROM accounts WHERE did = ?",
|
||||
[did]
|
||||
[did],
|
||||
);
|
||||
|
||||
if (existingResult?.values?.length) {
|
||||
result.warnings.push(`Account with DID ${did} already exists, skipping`);
|
||||
result.warnings.push(
|
||||
`Account with DID ${did} already exists, skipping`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (account.mnemonic) {
|
||||
await importFromMnemonic(account.mnemonic, account.derivationPath);
|
||||
result.accountsMigrated++;
|
||||
} else {
|
||||
result.errors.push(`Account with DID ${did} has no mnemonic, skipping`);
|
||||
result.errors.push(
|
||||
`Account with DID ${did} has no mnemonic, skipping`,
|
||||
);
|
||||
}
|
||||
|
||||
logger.info("[MigrationService] Successfully migrated account", {
|
||||
did,
|
||||
dateCreated: account.dateCreated
|
||||
dateCreated: account.dateCreated,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorMessage = `Failed to migrate account ${did}: ${error}`;
|
||||
result.errors.push(errorMessage);
|
||||
logger.error("[MigrationService] Account migration failed:", {
|
||||
error,
|
||||
did
|
||||
did,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1211,7 +1271,10 @@ export async function migrateAccounts(): Promise<MigrationResult> {
|
||||
const errorMessage = `Account migration failed: ${error}`;
|
||||
result.errors.push(errorMessage);
|
||||
result.success = false;
|
||||
logger.error("[MigrationService] Complete account migration failed:", error);
|
||||
logger.error(
|
||||
"[MigrationService] Complete account migration failed:",
|
||||
error,
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user