Complete Enhanced Triple Migration Pattern for contact components

- Migrate ContactBulkActions, ContactInputForm, ContactListHeader, ContactListItem, LargeIdenticonModal, and ContactsView to PlatformServiceMixin
- Add comprehensive deep linking support to CapacitorPlatformService and WebPlatformService
- Enhance PlatformService with new database operations and deep link handling
- Update service worker and documentation for migration progress
- Fix TypeScript type errors in util.ts and deepLinks.ts
- Streamline circular dependency analysis and migration tracking docs
This commit is contained in:
Matthew Raymer
2025-07-16 08:41:13 +00:00
parent 8dd73950f5
commit b1ef7fb9ee
15 changed files with 433 additions and 201 deletions

View File

@@ -8,7 +8,6 @@ import { useClipboard } from "@vueuse/core";
import { DEFAULT_PUSH_SERVER, NotificationIface } from "../constants/app";
import { Account, AccountEncrypted } from "../db/tables/accounts";
import { Contact, ContactWithJsonStrings } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { DEFAULT_PASSKEY_EXPIRATION_MINUTES } from "../db/tables/settings";
import {
arrayBufferToBase64,
@@ -33,8 +32,41 @@ import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import { IIdentifier } from "@veramo/core";
import { parseJsonField } from "@/db/databaseUtil";
import { DEFAULT_ROOT_DERIVATION_PATH } from "./crypto";
import * as databaseUtil from "../db/databaseUtil";
// Self-contained utility functions to replace databaseUtil dependencies
function parseJsonField<T>(value: unknown, defaultValue: T): T {
if (typeof value === "string") {
try {
return JSON.parse(value);
} catch {
return defaultValue;
}
}
return (value as T) || defaultValue;
}
function mapQueryResultToValues(
record: { columns: string[]; values: unknown[][] } | undefined,
): Array<Record<string, unknown>> {
if (!record || !record.columns || !record.values) {
return [];
}
return record.values.map((row) => {
const obj: Record<string, unknown> = {};
record.columns.forEach((column, index) => {
obj[column] = row[index];
});
return obj;
});
}
// Platform service access for database operations
async function getPlatformService() {
return PlatformServiceFactory.getInstance();
}
export interface GiverReceiverInputInfo {
did?: string;
@@ -488,7 +520,7 @@ export type AccountKeyInfo = Account & KeyMetaWithPrivate;
export const retrieveAccountCount = async (): Promise<number> => {
let result = 0;
const platformService = PlatformServiceFactory.getInstance();
const platformService = await getPlatformService();
const dbResult = await platformService.dbQuery(
`SELECT COUNT(*) FROM accounts`,
);
@@ -500,12 +532,10 @@ export const retrieveAccountCount = async (): Promise<number> => {
};
export const retrieveAccountDids = async (): Promise<string[]> => {
const platformService = PlatformServiceFactory.getInstance();
const platformService = await getPlatformService();
const dbAccounts = await platformService.dbQuery(`SELECT did FROM accounts`);
const allDids =
databaseUtil
.mapQueryResultToValues(dbAccounts)
?.map((row) => row[0] as string) || [];
mapQueryResultToValues(dbAccounts)?.map((row) => row[0] as string) || [];
return allDids;
};
@@ -519,12 +549,12 @@ export const retrieveAccountMetadata = async (
activeDid: string,
): Promise<Account | undefined> => {
let result: Account | undefined = undefined;
const platformService = PlatformServiceFactory.getInstance();
const platformService = await getPlatformService();
const dbAccount = await platformService.dbQuery(
`SELECT * FROM accounts WHERE did = ?`,
[activeDid],
);
const account = databaseUtil.mapQueryResultToValues(dbAccount)[0] as Account;
const account = mapQueryResultToValues(dbAccount)[0] as Account;
if (account) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { identity, mnemonic, ...metadata } = account;
@@ -545,7 +575,7 @@ export const retrieveFullyDecryptedAccount = async (
activeDid: string,
): Promise<Account | undefined> => {
let result: Account | undefined = undefined;
const platformService = PlatformServiceFactory.getInstance();
const platformService = await getPlatformService();
const dbSecrets = await platformService.dbQuery(
`SELECT secretBase64 from secret`,
);
@@ -571,7 +601,7 @@ export const retrieveFullyDecryptedAccount = async (
) {
throw new Error("Account not found.");
}
const fullAccountData = databaseUtil.mapQueryResultToValues(
const fullAccountData = mapQueryResultToValues(
dbAccount,
)[0] as AccountEncrypted;
const identityEncr = base64ToArrayBuffer(fullAccountData.identityEncrBase64);
@@ -586,9 +616,9 @@ export const retrieveFullyDecryptedAccount = async (
export const retrieveAllAccountsMetadata = async (): Promise<
AccountEncrypted[]
> => {
const platformService = PlatformServiceFactory.getInstance();
const platformService = await getPlatformService();
const dbAccounts = await platformService.dbQuery(`SELECT * FROM accounts`);
const accounts = databaseUtil.mapQueryResultToValues(dbAccounts) as Account[];
const accounts = mapQueryResultToValues(dbAccounts) as Account[];
const result = accounts.map((account) => {
return account as AccountEncrypted;
});
@@ -605,7 +635,7 @@ export async function saveNewIdentity(
): Promise<void> {
try {
// add to the new sql db
const platformService = PlatformServiceFactory.getInstance();
const platformService = await getPlatformService();
const secrets = await platformService.dbQuery(
`SELECT secretBase64 FROM secret`,
@@ -681,14 +711,12 @@ export const registerAndSavePasskey = async (
passkeyCredIdHex,
publicKeyHex: Buffer.from(publicKeyBytes).toString("hex"),
};
const insertStatement = databaseUtil.generateInsertStatement(
const platformService = await getPlatformService();
const insertStatement = platformService.generateInsertStatement(
account,
"accounts",
);
await PlatformServiceFactory.getInstance().dbExec(
insertStatement.sql,
insertStatement.params,
);
await platformService.dbExec(insertStatement.sql, insertStatement.params);
return account;
};
@@ -696,17 +724,19 @@ export const registerSaveAndActivatePasskey = async (
keyName: string,
): Promise<Account> => {
const account = await registerAndSavePasskey(keyName);
await databaseUtil.updateDefaultSettings({ activeDid: account.did });
await databaseUtil.updateDidSpecificSettings(account.did, {
const platformService = await getPlatformService();
await platformService.updateDefaultSettings({ activeDid: account.did });
await platformService.updateDidSpecificSettings(account.did, {
isRegistered: false,
});
return account;
};
export const getPasskeyExpirationSeconds = async (): Promise<number> => {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
const platformService = await getPlatformService();
const settings = await platformService.retrieveSettingsForActiveAccount();
return (
(settings?.passkeyExpirationMinutes ?? DEFAULT_PASSKEY_EXPIRATION_MINUTES) *
(settings?.passkeyExpirationMinutes ?? DEFAULT_PASSKEY_EXPIRATION_MINUTES) as number *
60
);
};
@@ -720,10 +750,11 @@ export const sendTestThroughPushServer = async (
subscriptionJSON: PushSubscriptionJSON,
skipFilter: boolean,
): Promise<AxiosResponse> => {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
const platformService = await getPlatformService();
const settings = await platformService.retrieveSettingsForActiveAccount();
let pushUrl: string = DEFAULT_PUSH_SERVER as string;
if (settings?.webPushServer) {
pushUrl = settings.webPushServer;
pushUrl = settings.webPushServer as string;
}
const newPayload = {
@@ -887,7 +918,7 @@ export const contactsToExportJson = (contacts: Contact[]): DatabaseExport => {
contact,
);
exContact.contactMethods = contact.contactMethods
? JSON.stringify(contact.contactMethods, [])
? JSON.stringify(parseJsonField(contact.contactMethods, []))
: undefined;
return exContact;
});
@@ -932,7 +963,7 @@ export async function importFromMnemonic(
// Handle erasures
if (shouldErase) {
const platformService = PlatformServiceFactory.getInstance();
const platformService = await getPlatformService();
await platformService.dbExec("DELETE FROM accounts");
}
@@ -942,7 +973,8 @@ export async function importFromMnemonic(
// Set up Test User #0 specific settings
if (isTestUser0) {
// Set up Test User #0 specific settings
await databaseUtil.updateDidSpecificSettings(newId.did, {
const platformService = await getPlatformService();
await platformService.updateDidSpecificSettings(newId.did, {
firstName: "User Zero",
isRegistered: true,
});