forked from jsnbuchanan/crowd-funder-for-time-pwa
WIP: BROKEN FOR ELECTRON: Fixes in progress
This commit is contained in:
@@ -127,10 +127,7 @@ export async function registerMigrations(): Promise<void> {
|
||||
}
|
||||
|
||||
export async function runMigrations(
|
||||
sqlExec: (
|
||||
sql: string,
|
||||
params?: unknown[],
|
||||
) => Promise<Array<QueryExecResult>>,
|
||||
sqlExec: (sql: string, params?: unknown[]) => Promise<Array<QueryExecResult>>,
|
||||
): Promise<void> {
|
||||
await registerMigrations();
|
||||
await migrationService.runMigrations(sqlExec);
|
||||
|
||||
@@ -123,35 +123,77 @@ export async function retrieveSettingsForActiveAccount(): Promise<Settings> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message to the database with proper handling of concurrent writes
|
||||
* @param message - The message to log
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
export async function logToDb(message: string): Promise<void> {
|
||||
const platform = PlatformServiceFactory.getInstance();
|
||||
const todayKey = new Date().toDateString();
|
||||
const fullMessage = `${new Date().toISOString()} ${message}`;
|
||||
|
||||
// Check if we have any logs for today
|
||||
const result = await platform.dbQuery(
|
||||
"SELECT message FROM logs WHERE date = ?",
|
||||
[todayKey],
|
||||
);
|
||||
try {
|
||||
// Try to insert first, if it fails due to UNIQUE constraint, update instead
|
||||
try {
|
||||
await platform.dbExec("INSERT INTO logs (date, message) VALUES (?, ?)", [
|
||||
todayKey,
|
||||
fullMessage,
|
||||
]);
|
||||
} catch (error) {
|
||||
// If insert fails due to UNIQUE constraint, update instead
|
||||
if (
|
||||
error instanceof Error &&
|
||||
error.message.includes("UNIQUE constraint failed")
|
||||
) {
|
||||
const result = await platform.dbQuery(
|
||||
"SELECT message FROM logs WHERE date = ?",
|
||||
[todayKey],
|
||||
);
|
||||
|
||||
if (!result || result.values.length === 0) {
|
||||
// If no logs for today, clear all previous logs
|
||||
await platform.dbExec("DELETE FROM logs");
|
||||
if (result && result.values.length > 0) {
|
||||
const prevMessages = result.values[0][0] as string;
|
||||
const updatedMessage = `${prevMessages}\n${fullMessage}`;
|
||||
|
||||
// Insert new log
|
||||
const fullMessage = `${new Date().toISOString()} ${message}`;
|
||||
await platform.dbExec("INSERT INTO logs (date, message) VALUES (?, ?)", [
|
||||
todayKey,
|
||||
fullMessage,
|
||||
]);
|
||||
} else {
|
||||
// Append to existing log
|
||||
const prevMessages = result.values[0][0] as string;
|
||||
const fullMessage = `${prevMessages}\n${new Date().toISOString()} ${message}`;
|
||||
await platform.dbExec("UPDATE logs SET message = ? WHERE date = ?", [
|
||||
updatedMessage,
|
||||
todayKey,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
// If it's a different error, rethrow it
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
await platform.dbExec("UPDATE logs SET message = ? WHERE date = ?", [
|
||||
fullMessage,
|
||||
todayKey,
|
||||
]);
|
||||
// Clean up old logs (keep only last 7 days) - do this less frequently
|
||||
// Only clean up if the date is different from the last cleanup
|
||||
const lastCleanupKey = "last_log_cleanup";
|
||||
const result = await platform.dbQuery(
|
||||
"SELECT value FROM settings WHERE key = ?",
|
||||
[lastCleanupKey],
|
||||
);
|
||||
|
||||
const lastCleanup = result?.values[0]?.[0] as string;
|
||||
if (!lastCleanup || lastCleanup !== todayKey) {
|
||||
const sevenDaysAgo = new Date();
|
||||
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
|
||||
await platform.dbExec("DELETE FROM logs WHERE date < ?", [
|
||||
sevenDaysAgo.toDateString(),
|
||||
]);
|
||||
|
||||
// Update last cleanup date
|
||||
await platform.dbExec(
|
||||
"INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)",
|
||||
[lastCleanupKey, todayKey],
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// Log to console as fallback
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Failed to log to database:", error);
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Original message:", message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,24 +2,33 @@ const { contextBridge, ipcRenderer } = require("electron");
|
||||
|
||||
const logger = {
|
||||
log: (message, ...args) => {
|
||||
// Always log in development, log with context in production
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
/* eslint-disable no-console */
|
||||
console.log(message, ...args);
|
||||
console.log(`[Preload] ${message}`, ...args);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
},
|
||||
warn: (message, ...args) => {
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
/* eslint-disable no-console */
|
||||
console.warn(message, ...args);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
// Always log warnings
|
||||
/* eslint-disable no-console */
|
||||
console.warn(`[Preload] ${message}`, ...args);
|
||||
/* eslint-enable no-console */
|
||||
},
|
||||
error: (message, ...args) => {
|
||||
// Always log errors
|
||||
/* eslint-disable no-console */
|
||||
console.error(message, ...args); // Errors should always be logged
|
||||
console.error(`[Preload] ${message}`, ...args);
|
||||
/* eslint-enable no-console */
|
||||
},
|
||||
info: (message, ...args) => {
|
||||
// Always log info in development, log with context in production
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
/* eslint-disable no-console */
|
||||
console.info(`[Preload] ${message}`, ...args);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Use a more direct path resolution approach
|
||||
@@ -41,7 +50,10 @@ const getPath = (pathType) => {
|
||||
}
|
||||
};
|
||||
|
||||
logger.log("Preload script starting...");
|
||||
logger.info("Preload script starting...");
|
||||
|
||||
// Force electron platform in the renderer process
|
||||
window.process = { env: { VITE_PLATFORM: "electron" } };
|
||||
|
||||
try {
|
||||
contextBridge.exposeInMainWorld("electronAPI", {
|
||||
@@ -65,6 +77,7 @@ try {
|
||||
env: {
|
||||
isElectron: true,
|
||||
isDev: process.env.NODE_ENV === "development",
|
||||
platform: "electron", // Explicitly set platform
|
||||
},
|
||||
// Path utilities
|
||||
getBasePath: () => {
|
||||
@@ -72,7 +85,7 @@ try {
|
||||
},
|
||||
});
|
||||
|
||||
logger.log("Preload script completed successfully");
|
||||
logger.info("Preload script completed successfully");
|
||||
} catch (error) {
|
||||
logger.error("Error in preload script:", error);
|
||||
}
|
||||
|
||||
@@ -43,14 +43,14 @@ export interface KeyMeta {
|
||||
derivationPath: string;
|
||||
registered?: boolean;
|
||||
profileImageUrl?: string;
|
||||
identity?: string; // Stringified IIdentifier object from Veramo
|
||||
passkeyCredIdHex?: string; // The Webauthn credential ID in hex, if this is from a passkey
|
||||
identity?: string; // Stringified IIdentifier object from Veramo
|
||||
passkeyCredIdHex?: string; // The Webauthn credential ID in hex, if this is from a passkey
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface QuantitativeValue extends GenericVerifiableCredential {
|
||||
'@type': 'QuantitativeValue';
|
||||
'@context': string | string[];
|
||||
"@type": "QuantitativeValue";
|
||||
"@context": string | string[];
|
||||
amountOfThisGood: number;
|
||||
unitCode: string;
|
||||
[key: string]: unknown;
|
||||
@@ -101,10 +101,10 @@ export interface Agent {
|
||||
}
|
||||
|
||||
export interface ClaimObject {
|
||||
'@type': string;
|
||||
'@context'?: string | string[];
|
||||
"@type": string;
|
||||
"@context"?: string | string[];
|
||||
fulfills?: Array<{
|
||||
'@type': string;
|
||||
"@type": string;
|
||||
identifier?: string;
|
||||
[key: string]: unknown;
|
||||
}>;
|
||||
@@ -119,16 +119,16 @@ export interface ClaimObject {
|
||||
}
|
||||
|
||||
export interface VerifiableCredentialClaim {
|
||||
'@context': string | string[];
|
||||
'@type': string;
|
||||
"@context": string | string[];
|
||||
"@type": string;
|
||||
type: string[];
|
||||
credentialSubject: ClaimObject;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface GiveVerifiableCredential extends GenericVerifiableCredential {
|
||||
'@type': 'GiveAction';
|
||||
'@context': string | string[];
|
||||
"@type": "GiveAction";
|
||||
"@context": string | string[];
|
||||
object?: GenericVerifiableCredential;
|
||||
agent?: Agent;
|
||||
participant?: {
|
||||
@@ -136,7 +136,7 @@ export interface GiveVerifiableCredential extends GenericVerifiableCredential {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
fulfills?: Array<{
|
||||
'@type': string;
|
||||
"@type": string;
|
||||
identifier?: string;
|
||||
[key: string]: unknown;
|
||||
}>;
|
||||
@@ -144,8 +144,8 @@ export interface GiveVerifiableCredential extends GenericVerifiableCredential {
|
||||
}
|
||||
|
||||
export interface OfferVerifiableCredential extends GenericVerifiableCredential {
|
||||
'@type': 'OfferAction';
|
||||
'@context': string | string[];
|
||||
"@type": "OfferAction";
|
||||
"@context": string | string[];
|
||||
object?: GenericVerifiableCredential;
|
||||
agent?: Agent;
|
||||
participant?: {
|
||||
@@ -155,7 +155,7 @@ export interface OfferVerifiableCredential extends GenericVerifiableCredential {
|
||||
itemOffered?: {
|
||||
description?: string;
|
||||
isPartOf?: {
|
||||
'@type': string;
|
||||
"@type": string;
|
||||
identifier: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
@@ -164,9 +164,10 @@ export interface OfferVerifiableCredential extends GenericVerifiableCredential {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface RegisterVerifiableCredential extends GenericVerifiableCredential {
|
||||
'@type': 'RegisterAction';
|
||||
'@context': string | string[];
|
||||
export interface RegisterVerifiableCredential
|
||||
extends GenericVerifiableCredential {
|
||||
"@type": "RegisterAction";
|
||||
"@context": string | string[];
|
||||
agent: {
|
||||
identifier: string;
|
||||
};
|
||||
|
||||
@@ -194,7 +194,9 @@ export class PeerSetup {
|
||||
},
|
||||
};
|
||||
|
||||
const credential = await navigator.credentials.get(options) as PublicKeyCredential;
|
||||
const credential = (await navigator.credentials.get(
|
||||
options,
|
||||
)) as PublicKeyCredential;
|
||||
// console.log("nav credential get", credential);
|
||||
|
||||
const response = credential?.response as AuthenticatorAssertionResponse;
|
||||
@@ -229,9 +231,7 @@ export class PeerSetup {
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=+$/, "");
|
||||
|
||||
const origSignature = Buffer.from(response?.signature).toString(
|
||||
"base64",
|
||||
);
|
||||
const origSignature = Buffer.from(response?.signature).toString("base64");
|
||||
this.signature = origSignature
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
@@ -327,10 +327,7 @@ export async function verifyJwtP256(
|
||||
const publicKeyBytes = peerDidToPublicKeyBytes(issuerDid);
|
||||
|
||||
// Use challenge in preimage construction
|
||||
const preimage = Buffer.concat([
|
||||
authDataFromBase,
|
||||
Buffer.from(challenge),
|
||||
]);
|
||||
const preimage = Buffer.concat([authDataFromBase, Buffer.from(challenge)]);
|
||||
|
||||
const isValid = p256.verify(
|
||||
finalSigBuffer,
|
||||
@@ -391,10 +388,7 @@ export async function verifyJwtWebCrypto(
|
||||
const finalSigBuffer = unwrapEC2Signature(sigBuffer);
|
||||
|
||||
// Use challenge in preimage construction
|
||||
const preimage = Buffer.concat([
|
||||
authDataFromBase,
|
||||
Buffer.from(challenge),
|
||||
]);
|
||||
const preimage = Buffer.concat([authDataFromBase, Buffer.from(challenge)]);
|
||||
|
||||
return verifyPeerSignature(preimage, issuerDid, finalSigBuffer);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ import {
|
||||
ClaimObject,
|
||||
VerifiableCredentialClaim,
|
||||
Agent,
|
||||
QuantitativeValue
|
||||
QuantitativeValue,
|
||||
} from "../interfaces/common";
|
||||
import { logger } from "../utils/logger";
|
||||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
||||
@@ -106,11 +106,12 @@ export const CONTACT_CONFIRM_URL_PATH_TIME_SAFARI = "/contact/confirm/";
|
||||
*/
|
||||
export const ENDORSER_CH_HANDLE_PREFIX = "https://endorser.ch/entity/";
|
||||
|
||||
export const BLANK_GENERIC_SERVER_RECORD: GenericCredWrapper<GenericVerifiableCredential> = {
|
||||
claim: {
|
||||
"@context": SCHEMA_ORG_CONTEXT,
|
||||
"@type": ""
|
||||
},
|
||||
export const BLANK_GENERIC_SERVER_RECORD: GenericCredWrapper<GenericVerifiableCredential> =
|
||||
{
|
||||
claim: {
|
||||
"@context": SCHEMA_ORG_CONTEXT,
|
||||
"@type": "",
|
||||
},
|
||||
handleId: "",
|
||||
id: "",
|
||||
issuedAt: "",
|
||||
@@ -200,10 +201,10 @@ const testRecursivelyOnStrings = (
|
||||
return input.some((item) => testRecursivelyOnStrings(item, test));
|
||||
} else if (input && typeof input === "object") {
|
||||
return Object.values(input as Record<string, unknown>).some((value) =>
|
||||
testRecursivelyOnStrings(value, test)
|
||||
testRecursivelyOnStrings(value, test),
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -545,7 +546,7 @@ export async function setPlanInCache(
|
||||
* @returns {string|undefined} User-friendly message or undefined if none found
|
||||
*/
|
||||
export function serverMessageForUser(error: unknown): string | undefined {
|
||||
if (error && typeof error === 'object' && 'response' in error) {
|
||||
if (error && typeof error === "object" && "response" in error) {
|
||||
const err = error as AxiosErrorResponse;
|
||||
return err.response?.data?.error?.message;
|
||||
}
|
||||
@@ -571,21 +572,26 @@ export function errorStringForLog(error: unknown) {
|
||||
// --- property '_value' closes the circle
|
||||
}
|
||||
let fullError = "" + error + " - JSON: " + stringifiedError;
|
||||
|
||||
if (error && typeof error === 'object' && 'response' in error) {
|
||||
|
||||
if (error && typeof error === "object" && "response" in error) {
|
||||
const err = error as AxiosErrorResponse;
|
||||
const errorResponseText = JSON.stringify(err.response);
|
||||
// for some reason, error.response is not included in stringify result (eg. for 400 errors on invite redemptions)
|
||||
if (!R.empty(errorResponseText) && !fullError.includes(errorResponseText)) {
|
||||
// add error.response stuff
|
||||
if (err.response?.config && err.config && R.equals(err.config, err.response.config)) {
|
||||
// but exclude "config" because it's already in there
|
||||
const newErrorResponseText = JSON.stringify(
|
||||
// for some reason, error.response is not included in stringify result (eg. for 400 errors on invite redemptions)
|
||||
if (!R.empty(errorResponseText) && !fullError.includes(errorResponseText)) {
|
||||
// add error.response stuff
|
||||
if (
|
||||
err.response?.config &&
|
||||
err.config &&
|
||||
R.equals(err.config, err.response.config)
|
||||
) {
|
||||
// but exclude "config" because it's already in there
|
||||
const newErrorResponseText = JSON.stringify(
|
||||
R.omit(["config"] as never[], err.response),
|
||||
);
|
||||
fullError += " - .response w/o same config JSON: " + newErrorResponseText;
|
||||
} else {
|
||||
fullError += " - .response JSON: " + errorResponseText;
|
||||
);
|
||||
fullError +=
|
||||
" - .response w/o same config JSON: " + newErrorResponseText;
|
||||
} else {
|
||||
fullError += " - .response JSON: " + errorResponseText;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -664,7 +670,7 @@ export function hydrateGive(
|
||||
"@type": "GiveAction",
|
||||
object: undefined,
|
||||
agent: undefined,
|
||||
fulfills: []
|
||||
fulfills: [],
|
||||
};
|
||||
|
||||
if (lastClaimId) {
|
||||
@@ -679,13 +685,13 @@ export function hydrateGive(
|
||||
vcClaim.recipient = { identifier: toDid };
|
||||
}
|
||||
vcClaim.description = description || undefined;
|
||||
|
||||
|
||||
if (amount && !isNaN(amount)) {
|
||||
const quantitativeValue: QuantitativeValue = {
|
||||
"@context": SCHEMA_ORG_CONTEXT,
|
||||
"@type": "QuantitativeValue",
|
||||
amountOfThisGood: amount,
|
||||
unitCode: unitCode || "HUR"
|
||||
unitCode: unitCode || "HUR",
|
||||
};
|
||||
vcClaim.object = quantitativeValue;
|
||||
}
|
||||
@@ -697,34 +703,34 @@ export function hydrateGive(
|
||||
|
||||
// Filter and add fulfills elements
|
||||
vcClaim.fulfills = vcClaim.fulfills.filter(
|
||||
(elem: { '@type': string }) => elem["@type"] !== "PlanAction"
|
||||
(elem: { "@type": string }) => elem["@type"] !== "PlanAction",
|
||||
);
|
||||
|
||||
|
||||
if (fulfillsProjectHandleId) {
|
||||
vcClaim.fulfills.push({
|
||||
"@type": "PlanAction",
|
||||
identifier: fulfillsProjectHandleId
|
||||
identifier: fulfillsProjectHandleId,
|
||||
});
|
||||
}
|
||||
|
||||
vcClaim.fulfills = vcClaim.fulfills.filter(
|
||||
(elem: { '@type': string }) => elem["@type"] !== "Offer"
|
||||
(elem: { "@type": string }) => elem["@type"] !== "Offer",
|
||||
);
|
||||
|
||||
|
||||
if (fulfillsOfferHandleId) {
|
||||
vcClaim.fulfills.push({
|
||||
"@type": "Offer",
|
||||
identifier: fulfillsOfferHandleId
|
||||
identifier: fulfillsOfferHandleId,
|
||||
});
|
||||
}
|
||||
|
||||
vcClaim.fulfills = vcClaim.fulfills.filter(
|
||||
(elem: { '@type': string }) =>
|
||||
elem["@type"] !== "DonateAction" && elem["@type"] !== "TradeAction"
|
||||
(elem: { "@type": string }) =>
|
||||
elem["@type"] !== "DonateAction" && elem["@type"] !== "TradeAction",
|
||||
);
|
||||
|
||||
vcClaim.fulfills.push({
|
||||
"@type": isTrade ? "TradeAction" : "DonateAction"
|
||||
|
||||
vcClaim.fulfills.push({
|
||||
"@type": isTrade ? "TradeAction" : "DonateAction",
|
||||
});
|
||||
|
||||
vcClaim.image = imageUrl || undefined;
|
||||
@@ -732,7 +738,7 @@ export function hydrateGive(
|
||||
if (providerPlanHandleId) {
|
||||
vcClaim.provider = {
|
||||
"@type": "PlanAction",
|
||||
identifier: providerPlanHandleId
|
||||
identifier: providerPlanHandleId,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -854,7 +860,7 @@ export function hydrateOffer(
|
||||
"@type": "OfferAction",
|
||||
object: undefined,
|
||||
agent: undefined,
|
||||
itemOffered: {}
|
||||
itemOffered: {},
|
||||
};
|
||||
|
||||
if (lastClaimId) {
|
||||
@@ -875,7 +881,7 @@ export function hydrateOffer(
|
||||
"@context": SCHEMA_ORG_CONTEXT,
|
||||
"@type": "QuantitativeValue",
|
||||
amountOfThisGood: amount,
|
||||
unitCode: unitCode || "HUR"
|
||||
unitCode: unitCode || "HUR",
|
||||
};
|
||||
vcClaim.object = quantitativeValue;
|
||||
}
|
||||
@@ -886,7 +892,7 @@ export function hydrateOffer(
|
||||
if (fulfillsProjectHandleId) {
|
||||
vcClaim.itemOffered.isPartOf = {
|
||||
"@type": "PlanAction",
|
||||
identifier: fulfillsProjectHandleId
|
||||
identifier: fulfillsProjectHandleId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1024,12 +1030,14 @@ export async function createAndSubmitClaim(
|
||||
logger.error("Error submitting claim:", error);
|
||||
const errorMessage: string =
|
||||
serverMessageForUser(error) ||
|
||||
(error && typeof error === 'object' && 'message' in error ? String(error.message) : undefined) ||
|
||||
(error && typeof error === "object" && "message" in error
|
||||
? String(error.message)
|
||||
: undefined) ||
|
||||
"Got some error submitting the claim. Check your permissions, network, and error logs.";
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: errorMessage
|
||||
error: errorMessage,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1061,10 +1069,7 @@ export async function generateEndorserJwtUrlForAccount(
|
||||
// Add the next key -- not recommended for the QR code for such a high resolution
|
||||
if (isContact) {
|
||||
const newDerivPath = nextDerivationPath(account.derivationPath);
|
||||
const nextPublicHex = deriveAddress(
|
||||
account.mnemonic,
|
||||
newDerivPath,
|
||||
)[2];
|
||||
const nextPublicHex = deriveAddress(account.mnemonic, newDerivPath)[2];
|
||||
const nextPublicEncKey = Buffer.from(nextPublicHex, "hex");
|
||||
const nextPublicEncKeyHash = sha256(nextPublicEncKey);
|
||||
const nextPublicEncKeyHashBase64 =
|
||||
@@ -1133,13 +1138,15 @@ export const capitalizeAndInsertSpacesBeforeCaps = (text: string) => {
|
||||
similar code is also contained in endorser-mobile
|
||||
**/
|
||||
const claimSummary = (
|
||||
claim: GenericVerifiableCredential | GenericCredWrapper<GenericVerifiableCredential>,
|
||||
claim:
|
||||
| GenericVerifiableCredential
|
||||
| GenericCredWrapper<GenericVerifiableCredential>,
|
||||
) => {
|
||||
if (!claim) {
|
||||
return "something";
|
||||
}
|
||||
let specificClaim: GenericVerifiableCredential;
|
||||
if ('claim' in claim) {
|
||||
if ("claim" in claim) {
|
||||
// It's a GenericCredWrapper
|
||||
specificClaim = claim.claim as GenericVerifiableCredential;
|
||||
} else {
|
||||
@@ -1180,7 +1187,7 @@ export const claimSpecialDescription = (
|
||||
contacts: Array<Contact>,
|
||||
) => {
|
||||
let claim = record.claim;
|
||||
if ('claim' in claim) {
|
||||
if ("claim" in claim) {
|
||||
claim = claim.claim as GenericVerifiableCredential;
|
||||
}
|
||||
|
||||
@@ -1189,12 +1196,23 @@ export const claimSpecialDescription = (
|
||||
const type = claimObj["@type"] || "UnknownType";
|
||||
|
||||
if (type === "AgreeAction") {
|
||||
return issuer + " agreed with " + claimSummary(claimObj.object as GenericVerifiableCredential);
|
||||
return (
|
||||
issuer +
|
||||
" agreed with " +
|
||||
claimSummary(claimObj.object as GenericVerifiableCredential)
|
||||
);
|
||||
} else if (isAccept(claim)) {
|
||||
return issuer + " accepted " + claimSummary(claimObj.object as GenericVerifiableCredential);
|
||||
return (
|
||||
issuer +
|
||||
" accepted " +
|
||||
claimSummary(claimObj.object as GenericVerifiableCredential)
|
||||
);
|
||||
} else if (type === "GiveAction") {
|
||||
const giveClaim = claim as GiveVerifiableCredential;
|
||||
const agent: Agent = giveClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = giveClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1209,7 +1227,10 @@ export const claimSpecialDescription = (
|
||||
return contactInfo + " gave" + offering + recipientInfo;
|
||||
} else if (type === "JoinAction") {
|
||||
const joinClaim = claim as ClaimObject;
|
||||
const agent: Agent = joinClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = joinClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1219,7 +1240,10 @@ export const claimSpecialDescription = (
|
||||
return contactInfo + " joined" + objectInfo;
|
||||
} else if (isOffer(claim)) {
|
||||
const offerClaim = claim as OfferVerifiableCredential;
|
||||
const agent: Agent = offerClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = offerClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1234,7 +1258,10 @@ export const claimSpecialDescription = (
|
||||
return contactInfo + " offered" + offering + offerRecipientInfo;
|
||||
} else if (type === "PlanAction") {
|
||||
const planClaim = claim as ClaimObject;
|
||||
const agent: Agent = planClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = planClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1244,7 +1271,10 @@ export const claimSpecialDescription = (
|
||||
return contactInfo + " planned" + objectInfo;
|
||||
} else if (type === "Tenure") {
|
||||
const tenureClaim = claim as ClaimObject;
|
||||
const agent: Agent = tenureClaim.agent || { identifier: undefined, did: undefined };
|
||||
const agent: Agent = tenureClaim.agent || {
|
||||
identifier: undefined,
|
||||
did: undefined,
|
||||
};
|
||||
const agentDid = agent.did || agent.identifier;
|
||||
const contactInfo = agentDid
|
||||
? didInfo(agentDid, activeDid, identifiers, contacts)
|
||||
@@ -1253,11 +1283,7 @@ export const claimSpecialDescription = (
|
||||
const objectInfo = object ? " " + claimSummary(object) : "";
|
||||
return contactInfo + " has tenure" + objectInfo;
|
||||
} else {
|
||||
return (
|
||||
issuer +
|
||||
" declared " +
|
||||
claimSummary(claim)
|
||||
);
|
||||
return issuer + " declared " + claimSummary(claim);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1333,35 +1359,39 @@ export async function register(
|
||||
contact: Contact,
|
||||
): Promise<{ success?: boolean; error?: string }> {
|
||||
try {
|
||||
const vcJwt = await createInviteJwt(activeDid, contact);
|
||||
const url = apiServer + "/api/v2/claim";
|
||||
const resp = await axios.post<{
|
||||
success?: {
|
||||
handleId?: string;
|
||||
const vcJwt = await createInviteJwt(activeDid, contact);
|
||||
const url = apiServer + "/api/v2/claim";
|
||||
const resp = await axios.post<{
|
||||
success?: {
|
||||
handleId?: string;
|
||||
embeddedRecordError?: string;
|
||||
};
|
||||
error?: string;
|
||||
message?: string;
|
||||
}>(url, { jwtEncoded: vcJwt });
|
||||
|
||||
if (resp.data?.success?.handleId) {
|
||||
return { success: true };
|
||||
} else if (resp.data?.success?.embeddedRecordError) {
|
||||
let message = "There was some problem with the registration and so it may not be complete.";
|
||||
|
||||
if (resp.data?.success?.handleId) {
|
||||
return { success: true };
|
||||
} else if (resp.data?.success?.embeddedRecordError) {
|
||||
let message =
|
||||
"There was some problem with the registration and so it may not be complete.";
|
||||
if (typeof resp.data.success.embeddedRecordError === "string") {
|
||||
message += " " + resp.data.success.embeddedRecordError;
|
||||
}
|
||||
return { error: message };
|
||||
} else {
|
||||
message += " " + resp.data.success.embeddedRecordError;
|
||||
}
|
||||
return { error: message };
|
||||
} else {
|
||||
logger.error("Registration error:", JSON.stringify(resp.data));
|
||||
return { error: "Got a server error when registering." };
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if (error && typeof error === 'object') {
|
||||
if (error && typeof error === "object") {
|
||||
const err = error as AxiosErrorResponse;
|
||||
const errorMessage = err.message ||
|
||||
(err.response?.data && typeof err.response.data === 'object' && 'message' in err.response.data
|
||||
? (err.response.data as { message: string }).message
|
||||
const errorMessage =
|
||||
err.message ||
|
||||
(err.response?.data &&
|
||||
typeof err.response.data === "object" &&
|
||||
"message" in err.response.data
|
||||
? (err.response.data as { message: string }).message
|
||||
: undefined);
|
||||
logger.error("Registration error:", errorMessage || JSON.stringify(err));
|
||||
return { error: errorMessage || "Got a server error when registering." };
|
||||
|
||||
@@ -30,19 +30,13 @@ import {
|
||||
simpleEncrypt,
|
||||
} from "../libs/crypto";
|
||||
import * as serverUtil from "../libs/endorserServer";
|
||||
import {
|
||||
containsHiddenDid,
|
||||
} from "../libs/endorserServer";
|
||||
import { containsHiddenDid } from "../libs/endorserServer";
|
||||
import {
|
||||
GenericCredWrapper,
|
||||
GenericVerifiableCredential,
|
||||
} from "../interfaces/common";
|
||||
import {
|
||||
GiveSummaryRecord,
|
||||
} from "../interfaces/records";
|
||||
import {
|
||||
OfferVerifiableCredential,
|
||||
} from "../interfaces/claims";
|
||||
import { GiveSummaryRecord } from "../interfaces/records";
|
||||
import { OfferVerifiableCredential } from "../interfaces/claims";
|
||||
import { KeyMeta } from "../interfaces/common";
|
||||
import { createPeerDid } from "../libs/crypto/vc/didPeer";
|
||||
import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer";
|
||||
@@ -406,10 +400,7 @@ export function offerGiverDid(
|
||||
export const canFulfillOffer = (
|
||||
veriClaim: GenericCredWrapper<GenericVerifiableCredential>,
|
||||
) => {
|
||||
return (
|
||||
veriClaim.claimType === "Offer" &&
|
||||
!!offerGiverDid(veriClaim)
|
||||
);
|
||||
return veriClaim.claimType === "Offer" && !!offerGiverDid(veriClaim);
|
||||
};
|
||||
|
||||
// return object with paths and arrays of DIDs for any keys ending in "VisibleToDid"
|
||||
@@ -478,8 +469,10 @@ export function findAllVisibleToDids(
|
||||
*
|
||||
**/
|
||||
|
||||
export interface AccountKeyInfo extends Omit<Account, 'derivationPath'>, Omit<KeyMeta, 'derivationPath'> {
|
||||
derivationPath?: string; // Make it optional to match Account type
|
||||
export interface AccountKeyInfo
|
||||
extends Omit<Account, "derivationPath">,
|
||||
Omit<KeyMeta, "derivationPath"> {
|
||||
derivationPath?: string; // Make it optional to match Account type
|
||||
}
|
||||
|
||||
export const retrieveAccountCount = async (): Promise<number> => {
|
||||
@@ -489,7 +482,7 @@ export const retrieveAccountCount = async (): Promise<number> => {
|
||||
`SELECT COUNT(*) FROM accounts`,
|
||||
);
|
||||
if (dbResult?.values?.[0]?.[0]) {
|
||||
result = dbResult.values[0][0] as number;
|
||||
result = dbResult.values[0][0] as number;
|
||||
}
|
||||
|
||||
if (USE_DEXIE_DB) {
|
||||
@@ -638,7 +631,7 @@ export const retrieveAllFullyDecryptedAccounts = async (): Promise<
|
||||
) as unknown as AccountEncrypted[];
|
||||
if (USE_DEXIE_DB) {
|
||||
const accountsDB = await accountsDBPromise;
|
||||
allAccounts = await accountsDB.accounts.toArray() as AccountEncrypted[];
|
||||
allAccounts = (await accountsDB.accounts.toArray()) as AccountEncrypted[];
|
||||
}
|
||||
return allAccounts;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,12 @@ import { FontAwesomeIcon } from "./libs/fontawesome";
|
||||
import Camera from "simple-vue-camera";
|
||||
import { logger } from "./utils/logger";
|
||||
|
||||
const platform = process.env.VITE_PLATFORM;
|
||||
const pwa_enabled = process.env.VITE_PWA_ENABLED === "true";
|
||||
|
||||
logger.error("Platform", { platform });
|
||||
logger.error("PWA enabled", { pwa_enabled });
|
||||
|
||||
// Global Error Handler
|
||||
function setupGlobalErrorHandler(app: VueApp) {
|
||||
logger.log("[App Init] Setting up global error handler");
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
import { initializeApp } from "./main.common";
|
||||
import { logger } from "./utils/logger";
|
||||
|
||||
const platform = process.env.VITE_PLATFORM;
|
||||
const pwa_enabled = process.env.VITE_PWA_ENABLED === "true";
|
||||
|
||||
logger.info("[Electron] Initializing app");
|
||||
logger.info("[Electron] Platform:", { platform });
|
||||
logger.info("[Electron] PWA enabled:", { pwa_enabled });
|
||||
|
||||
if (pwa_enabled) {
|
||||
logger.warn("[Electron] PWA is enabled, but not supported in electron");
|
||||
}
|
||||
|
||||
const app = initializeApp();
|
||||
app.mount("#app");
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { initBackend } from "absurd-sql/dist/indexeddb-main-thread";
|
||||
import { initializeApp } from "./main.common";
|
||||
import { logger } from "./utils/logger";
|
||||
|
||||
const platform = process.env.VITE_PLATFORM;
|
||||
const pwa_enabled = process.env.VITE_PWA_ENABLED === "true";
|
||||
|
||||
logger.error("[Web] PWA enabled", { pwa_enabled });
|
||||
logger.error("[Web] Platform", { platform });
|
||||
|
||||
// Only import service worker for web builds
|
||||
if (
|
||||
process.env.VITE_PLATFORM !== "electron" &&
|
||||
process.env.VITE_PWA_ENABLED === "true"
|
||||
) {
|
||||
if (platform !== "electron" && pwa_enabled) {
|
||||
import("./registerServiceWorker"); // Web PWA support
|
||||
}
|
||||
|
||||
@@ -24,6 +28,10 @@ function sqlInit() {
|
||||
// workers through the main thread
|
||||
initBackend(worker);
|
||||
}
|
||||
sqlInit();
|
||||
if (platform === "web" || platform === "development") {
|
||||
sqlInit();
|
||||
} else {
|
||||
logger.info("[Web] SQL not initialized for platform", { platform });
|
||||
}
|
||||
|
||||
app.mount("#app");
|
||||
|
||||
@@ -22,12 +22,12 @@ interface AbsurdSqlDatabase {
|
||||
) => Promise<{ changes: number; lastId?: number }>;
|
||||
}
|
||||
|
||||
class AbsurdSqlDatabaseService implements DatabaseService {
|
||||
class AbsurdSqlDatabaseService<T> implements DatabaseService {
|
||||
private static instance: AbsurdSqlDatabaseService | null = null;
|
||||
private db: AbsurdSqlDatabase | null;
|
||||
private initialized: boolean;
|
||||
private initializationPromise: Promise<void> | null = null;
|
||||
private operationQueue: Array<QueuedOperation<any>> = [];
|
||||
private operationQueue: Array<QueuedOperation<T>> = [];
|
||||
private isProcessingQueue: boolean = false;
|
||||
|
||||
private constructor() {
|
||||
|
||||
@@ -4,7 +4,13 @@ import {
|
||||
StartScanOptions,
|
||||
LensFacing,
|
||||
} from "@capacitor-mlkit/barcode-scanning";
|
||||
import { QRScannerService, ScanListener, QRScannerOptions, CameraStateListener, CameraState } from "./types";
|
||||
import {
|
||||
QRScannerService,
|
||||
ScanListener,
|
||||
QRScannerOptions,
|
||||
CameraStateListener,
|
||||
CameraState,
|
||||
} from "./types";
|
||||
import { logger } from "@/utils/logger";
|
||||
|
||||
export class CapacitorQRScanner implements QRScannerService {
|
||||
@@ -96,7 +102,10 @@ export class CapacitorQRScanner implements QRScannerService {
|
||||
|
||||
// Check if scanning is supported
|
||||
if (!(await this.isSupported())) {
|
||||
this.updateCameraState("error", "QR scanning not supported on this device");
|
||||
this.updateCameraState(
|
||||
"error",
|
||||
"QR scanning not supported on this device",
|
||||
);
|
||||
throw new Error("QR scanning not supported on this device");
|
||||
}
|
||||
|
||||
|
||||
@@ -512,7 +512,10 @@ export class WebInlineQRScanner implements QRScannerService {
|
||||
this.scanAttempts = 0;
|
||||
this.lastScanTime = Date.now();
|
||||
this.updateCameraState("initializing", "Starting camera...");
|
||||
logger.error(`[WebInlineQRScanner:${this.id}] Starting scan with options:`, this.options);
|
||||
logger.error(
|
||||
`[WebInlineQRScanner:${this.id}] Starting scan with options:`,
|
||||
this.options,
|
||||
);
|
||||
|
||||
// Get camera stream with options
|
||||
logger.error(
|
||||
|
||||
@@ -121,10 +121,10 @@ export class DeepLinkHandler {
|
||||
|
||||
// Validate route exists before proceeding
|
||||
if (!this.ROUTE_MAP[routePath]) {
|
||||
throw {
|
||||
code: "INVALID_ROUTE",
|
||||
throw {
|
||||
code: "INVALID_ROUTE",
|
||||
message: `Invalid route path: ${routePath}`,
|
||||
details: { routePath }
|
||||
details: { routePath },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@ export const logger = {
|
||||
info: (message: string, ...args: unknown[]) => {
|
||||
if (
|
||||
process.env.NODE_ENV !== "production" ||
|
||||
process.env.VITE_PLATFORM === "capacitor"
|
||||
process.env.VITE_PLATFORM === "capacitor" ||
|
||||
process.env.VITE_PLATFORM === "electron"
|
||||
) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(message, ...args);
|
||||
@@ -53,7 +54,8 @@ export const logger = {
|
||||
warn: (message: string, ...args: unknown[]) => {
|
||||
if (
|
||||
process.env.NODE_ENV !== "production" ||
|
||||
process.env.VITE_PLATFORM === "capacitor"
|
||||
process.env.VITE_PLATFORM === "capacitor" ||
|
||||
process.env.VITE_PLATFORM === "electron"
|
||||
) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(message, ...args);
|
||||
|
||||
@@ -995,8 +995,8 @@ export default class ContactsView extends Vue {
|
||||
newContact as unknown as Record<string, unknown>,
|
||||
"contacts",
|
||||
);
|
||||
console.log("sql", sql);
|
||||
console.log("params", params);
|
||||
logger.error("sql", sql);
|
||||
logger.error("params", params);
|
||||
let contactPromise = platformService.dbExec(sql, params);
|
||||
if (USE_DEXIE_DB) {
|
||||
// @ts-expect-error since the result of this promise won't be used, and this will go away soon
|
||||
|
||||
@@ -90,15 +90,12 @@ import { AppString, NotificationIface, USE_DEXIE_DB } from "../constants/app";
|
||||
import * as databaseUtil from "../db/databaseUtil";
|
||||
import {
|
||||
accountsDBPromise,
|
||||
db,
|
||||
retrieveSettingsForActiveAccount,
|
||||
} from "../db/index";
|
||||
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
|
||||
import {
|
||||
DEFAULT_ROOT_DERIVATION_PATH,
|
||||
deriveAddress,
|
||||
newIdentifier,
|
||||
simpleEncrypt,
|
||||
} from "../libs/crypto";
|
||||
import { retrieveAccountCount, saveNewIdentity } from "../libs/util";
|
||||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
||||
|
||||
Reference in New Issue
Block a user