diff --git a/-1748433586226.log b/-1748433586226.log deleted file mode 100644 index c460a7d7..00000000 --- a/-1748433586226.log +++ /dev/null @@ -1,101 +0,0 @@ -VM5:29 [Preload] Preload script starting... -VM5:29 [Preload] Preload script completed successfully -main.common-DiOUyXe7.js:27 Platform Object -error @ main.common-DiOUyXe7.js:27 -main.common-DiOUyXe7.js:27 PWA enabled Object -error @ main.common-DiOUyXe7.js:27 -main.common-DiOUyXe7.js:27 [Web] PWA enabled Object -error @ main.common-DiOUyXe7.js:27 -main.common-DiOUyXe7.js:27 [Web] Platform Object -error @ main.common-DiOUyXe7.js:27 -main.common-DiOUyXe7.js:29 Opened! -main.common-DiOUyXe7.js:2552 Failed to log to database: Error: no such column: value - at E.handleError (main.common-DiOUyXe7.js:27:21133) - at E.exec (main.common-DiOUyXe7.js:27:19785) - at Rc.processQueue (main.common-DiOUyXe7.js:2379:2368) -F7 @ main.common-DiOUyXe7.js:2552 -main.common-DiOUyXe7.js:2552 Original message: PWA enabled - [{"pwa_enabled":false}] -F7 @ main.common-DiOUyXe7.js:2552 -main.common-DiOUyXe7.js:2552 Failed to log to database: Error: no such column: value - at E.handleError (main.common-DiOUyXe7.js:27:21133) - at E.exec (main.common-DiOUyXe7.js:27:19785) - at Rc.processQueue (main.common-DiOUyXe7.js:2379:2368) - at main.common-DiOUyXe7.js:2379:2816 - at new Promise () - at Rc.queueOperation (main.common-DiOUyXe7.js:2379:2685) - at Rc.query (main.common-DiOUyXe7.js:2379:3378) - at async F7 (main.common-DiOUyXe7.js:2552:117) -F7 @ main.common-DiOUyXe7.js:2552 -main.common-DiOUyXe7.js:2552 Original message: [Web] PWA enabled - [{"pwa_enabled":false}] -F7 @ main.common-DiOUyXe7.js:2552 -main.common-DiOUyXe7.js:2552 Failed to log to database: Error: no such column: value - at E.handleError (main.common-DiOUyXe7.js:27:21133) - at E.exec (main.common-DiOUyXe7.js:27:19785) - at Rc.processQueue (main.common-DiOUyXe7.js:2379:2368) - at main.common-DiOUyXe7.js:2379:2816 - at new Promise () - at Rc.queueOperation (main.common-DiOUyXe7.js:2379:2685) - at Rc.query (main.common-DiOUyXe7.js:2379:3378) - at async F7 (main.common-DiOUyXe7.js:2552:117) -F7 @ main.common-DiOUyXe7.js:2552 -main.common-DiOUyXe7.js:2552 Original message: [Web] Platform - [{"platform":"web"}] -F7 @ main.common-DiOUyXe7.js:2552 -main.common-DiOUyXe7.js:2552 Failed to log to database: Error: no such column: value - at E.handleError (main.common-DiOUyXe7.js:27:21133) - at E.exec (main.common-DiOUyXe7.js:27:19785) - at Rc.processQueue (main.common-DiOUyXe7.js:2379:2368) - at main.common-DiOUyXe7.js:2379:2816 - at new Promise () - at Rc.queueOperation (main.common-DiOUyXe7.js:2379:2685) - at Rc.query (main.common-DiOUyXe7.js:2379:3378) - at async F7 (main.common-DiOUyXe7.js:2552:117) -F7 @ main.common-DiOUyXe7.js:2552 -main.common-DiOUyXe7.js:2552 Original message: Platform - [{"platform":"web"}] -F7 @ main.common-DiOUyXe7.js:2552 -main.common-DiOUyXe7.js:2100 - - - GET https://api.endorser.ch/api/report/rateLimits 400 (Bad Request) -(anonymous) @ main.common-DiOUyXe7.js:2100 -xhr @ main.common-DiOUyXe7.js:2100 -p6 @ main.common-DiOUyXe7.js:2102 -_request @ main.common-DiOUyXe7.js:2103 -request @ main.common-DiOUyXe7.js:2102 -Yc. @ main.common-DiOUyXe7.js:2103 -(anonymous) @ main.common-DiOUyXe7.js:2098 -dJ @ main.common-DiOUyXe7.js:2295 -main.common-DiOUyXe7.js:2100 - - - GET https://api.endorser.ch/api/report/rateLimits 400 (Bad Request) -(anonymous) @ main.common-DiOUyXe7.js:2100 -xhr @ main.common-DiOUyXe7.js:2100 -p6 @ main.common-DiOUyXe7.js:2102 -_request @ main.common-DiOUyXe7.js:2103 -request @ main.common-DiOUyXe7.js:2102 -Yc. @ main.common-DiOUyXe7.js:2103 -(anonymous) @ main.common-DiOUyXe7.js:2098 -dJ @ main.common-DiOUyXe7.js:2295 -await in dJ -checkRegistrationStatus @ HomeView-DJMSCuMg.js:1 -mounted @ HomeView-DJMSCuMg.js:1 -XMLHttpRequest.send -(anonymous) @ main.common-DiOUyXe7.js:2100 -xhr @ main.common-DiOUyXe7.js:2100 -p6 @ main.common-DiOUyXe7.js:2102 -_request @ main.common-DiOUyXe7.js:2103 -request @ main.common-DiOUyXe7.js:2102 -Yc. @ main.common-DiOUyXe7.js:2103 -(anonymous) @ main.common-DiOUyXe7.js:2098 -ZG @ main.common-DiOUyXe7.js:2295 -await in ZG -initializeIdentity @ HomeView-DJMSCuMg.js:1 -XMLHttpRequest.send -(anonymous) @ main.common-DiOUyXe7.js:2100 -xhr @ main.common-DiOUyXe7.js:2100 -p6 @ main.common-DiOUyXe7.js:2102 -_request @ main.common-DiOUyXe7.js:2103 -request @ main.common-DiOUyXe7.js:2102 -Yc. @ main.common-DiOUyXe7.js:2103 -(anonymous) @ main.common-DiOUyXe7.js:2098 -dJ @ main.common-DiOUyXe7.js:2295 diff --git a/package-lock.json b/package-lock.json index c0e0569a..3a193851 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,6 +48,7 @@ "absurd-sql": "^0.0.54", "asn1-ber": "^1.2.2", "axios": "^1.6.8", + "better-sqlite3-multiple-ciphers": "^11.10.0", "cbor-x": "^1.5.9", "class-transformer": "^0.5.1", "dexie": "^3.2.7", @@ -55,6 +56,7 @@ "did-jwt": "^7.4.7", "did-resolver": "^4.1.0", "dotenv": "^16.0.3", + "electron-json-storage": "^4.6.0", "ethereum-cryptography": "^2.1.3", "ethereumjs-util": "^7.1.5", "jdenticon": "^3.2.0", @@ -11998,6 +12000,17 @@ "node": ">=12.0.0" } }, + "node_modules/better-sqlite3-multiple-ciphers": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/better-sqlite3-multiple-ciphers/-/better-sqlite3-multiple-ciphers-11.10.0.tgz", + "integrity": "sha512-/dKO3lKuJFbmuzh80uN2cmMsz8iyTskGB2l/fd9X6rt1P3EPIOvRUIxD7Qim8gLygUPB/u+db8byZGumOOdp3g==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + } + }, "node_modules/big-integer": { "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", @@ -13418,7 +13431,6 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "devOptional": true, "license": "MIT" }, "node_modules/concat-stream": { @@ -15249,6 +15261,65 @@ "node": ">=12" } }, + "node_modules/electron-json-storage": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/electron-json-storage/-/electron-json-storage-4.6.0.tgz", + "integrity": "sha512-gAgNsnA7tEtV9LzzOnZTyVIb3cQtCva+bEBVT5pbRGU8ZSZTVKPBrTxIAYjeVfdSjyNXgfb1mr/CZrOJgeHyqg==", + "license": "MIT", + "dependencies": { + "async": "^2.0.0", + "lockfile": "^1.0.4", + "lodash": "^4.0.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.1", + "write-file-atomic": "^2.4.2" + } + }, + "node_modules/electron-json-storage/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/electron-json-storage/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/electron-json-storage/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/electron-json-storage/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, "node_modules/electron-publish": { "version": "25.1.7", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz", @@ -17520,7 +17591,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", - "devOptional": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -17554,7 +17624,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -17565,7 +17634,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -18168,7 +18236,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "devOptional": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -18202,7 +18269,6 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "devOptional": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -20562,11 +20628,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lockfile": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", + "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", + "license": "ISC", + "dependencies": { + "signal-exit": "^3.0.2" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, "license": "MIT" }, "node_modules/lodash.clonedeep": { @@ -23729,7 +23803,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" diff --git a/package.json b/package.json index 04ce07c9..1cebe094 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,10 @@ "check:ios-device": "xcrun xctrace list devices 2>&1 | grep -w 'Booted' || (echo 'No iOS simulator running' && exit 1)", "clean:electron": "rimraf dist-electron", "build:pywebview": "vite build --config vite.config.pywebview.mts", - "build:electron": "npm run clean:electron && npm run build:web && tsc -p tsconfig.electron.json && vite build --config vite.config.electron.mts && node scripts/build-electron.js", - "build:capacitor": "vite build --mode capacitor --config vite.config.capacitor.mts", "build:web": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts", + "build:web:electron": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.electron.mts --mode electron", + "build:electron": "npm run clean:electron && npm run build:web:electron && tsc -p tsconfig.electron.json && vite build --config vite.config.electron.mts && node scripts/build-electron.js", + "build:capacitor": "vite build --mode capacitor --config vite.config.capacitor.mts", "electron:dev": "npm run build && electron .", "electron:start": "electron .", "clean:android": "adb uninstall app.timesafari.app || true", @@ -86,6 +87,7 @@ "absurd-sql": "^0.0.54", "asn1-ber": "^1.2.2", "axios": "^1.6.8", + "better-sqlite3-multiple-ciphers": "^11.10.0", "cbor-x": "^1.5.9", "class-transformer": "^0.5.1", "dexie": "^3.2.7", @@ -93,6 +95,7 @@ "did-jwt": "^7.4.7", "did-resolver": "^4.1.0", "dotenv": "^16.0.3", + "electron-json-storage": "^4.6.0", "ethereum-cryptography": "^2.1.3", "ethereumjs-util": "^7.1.5", "jdenticon": "^3.2.0", diff --git a/src/App.vue b/src/App.vue index 91bce243..f66ffafe 100644 --- a/src/App.vue +++ b/src/App.vue @@ -459,9 +459,9 @@ export default class App extends Vue { return true; } - const serverSubscription = { - ...subscription, - }; + const serverSubscription = typeof subscription === "object" && subscription !== null + ? { ...subscription } + : {}; if (!allGoingOff) { serverSubscription["notifyType"] = notification.title; logger.log( diff --git a/src/electron/main.ts b/src/electron/main.ts index e29f5685..54f251c3 100644 --- a/src/electron/main.ts +++ b/src/electron/main.ts @@ -1,6 +1,20 @@ -import { app, BrowserWindow } from "electron"; +import { app, BrowserWindow, ipcMain } from "electron"; import path from "path"; import fs from "fs"; +import { CapacitorSQLiteElectron } from '@capacitor-community/sqlite/electron/dist/plugin'; + +// Initialize SQLite plugin for Electron +const sqlitePlugin = new CapacitorSQLiteElectron(); + +// Set up IPC handler for SQLite +ipcMain.handle('capacitor-sqlite', async (_event, ...args) => { + return sqlitePlugin.handle(_event, ...args); +}); + +// Initialize SQLite when app is ready +app.whenReady().then(() => { + createWindow(); +}); // Simple logger implementation const logger = { diff --git a/src/main.electron.ts b/src/main.electron.ts index c71807af..5898f928 100644 --- a/src/main.electron.ts +++ b/src/main.electron.ts @@ -1,5 +1,20 @@ import { initializeApp } from "./main.common"; import { logger } from "./utils/logger"; +import { Capacitor } from '@capacitor/core'; +import { CapacitorSQLite } from '@capacitor-community/sqlite'; + +// Initialize Capacitor for Electron +Object.defineProperty(Capacitor, 'isNativePlatform', { + get: () => true, + configurable: true +}); + +// Initialize SQLite plugin for Electron +if (typeof window !== 'undefined') { + // Register the plugin globally + window.CapacitorSQLite = CapacitorSQLite; + logger.info("[Electron] SQLite plugin initialized in native mode"); +} const platform = process.env.VITE_PLATFORM; const pwa_enabled = process.env.VITE_PWA_ENABLED === "true"; diff --git a/src/services/platforms/ElectronPlatformService.ts b/src/services/platforms/ElectronPlatformService.ts index 5bdd455f..dc0582b1 100644 --- a/src/services/platforms/ElectronPlatformService.ts +++ b/src/services/platforms/ElectronPlatformService.ts @@ -8,7 +8,6 @@ import { QueryExecResult, SqlValue } from "@/interfaces/database"; import { SQLiteConnection, SQLiteDBConnection, - CapacitorSQLite, Changes, } from "@capacitor-community/sqlite"; import { DEFAULT_ENDORSER_API_SERVER } from "@/constants/app"; @@ -33,7 +32,11 @@ export class ElectronPlatformService implements PlatformService { private initialized = false; constructor() { - this.sqlite = new SQLiteConnection(CapacitorSQLite); + // Ensure we're using the native implementation + if (!window.CapacitorSQLite) { + throw new Error("CapacitorSQLite not initialized in Electron"); + } + this.sqlite = new SQLiteConnection(window.CapacitorSQLite); } private async initializeDatabase(): Promise { @@ -42,13 +45,13 @@ export class ElectronPlatformService implements PlatformService { } try { - // Create/Open database + // Create/Open database with native implementation this.db = await this.sqlite.createConnection( this.dbName, false, "no-encryption", 1, - false, + true // Use native implementation ); await this.db.open(); diff --git a/src/types/capacitor-sqlite-electron.d.ts b/src/types/capacitor-sqlite-electron.d.ts new file mode 100644 index 00000000..09269124 --- /dev/null +++ b/src/types/capacitor-sqlite-electron.d.ts @@ -0,0 +1,6 @@ +declare module '@capacitor-community/sqlite/electron/dist/plugin' { + export class CapacitorSQLiteElectron { + constructor(); + handle(event: Electron.IpcMainInvokeEvent, ...args: any[]): Promise; + } +} \ No newline at end of file diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 9cf4b740..28749dd4 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -1,4 +1,11 @@ import type { QueryExecResult, SqlValue } from "./database"; +import type { CapacitorSQLite } from '@capacitor-community/sqlite'; + +declare global { + interface Window { + CapacitorSQLite: typeof CapacitorSQLite; + } +} declare module '@jlongster/sql.js' { interface SQL { diff --git a/src/types/jeepq-sqlite.d.ts b/src/types/jeepq-sqlite.d.ts new file mode 100644 index 00000000..13c76fe8 --- /dev/null +++ b/src/types/jeepq-sqlite.d.ts @@ -0,0 +1 @@ +declare module '@jeepq/sqlite/loader'; \ No newline at end of file diff --git a/vite.config.electron.mts b/vite.config.electron.mts index 07188939..14d5c8be 100644 --- a/vite.config.electron.mts +++ b/vite.config.electron.mts @@ -2,13 +2,24 @@ import { defineConfig, mergeConfig } from "vite"; import { createBuildConfig } from "./vite.config.common.mts"; import path from 'path'; -export default defineConfig(async () => { +export default defineConfig(async ({ mode }) => { const baseConfig = await createBuildConfig('electron'); + const isWebBuild = mode === 'electron'; return mergeConfig(baseConfig, { build: { - outDir: 'dist-electron', - rollupOptions: { + outDir: isWebBuild ? 'dist' : 'dist-electron', + rollupOptions: isWebBuild ? { + // Web app build configuration + input: path.resolve(__dirname, 'index.html'), + output: { + format: 'esm', + entryFileNames: 'assets/[name]-[hash].js', + chunkFileNames: 'assets/[name]-[hash].js', + assetFileNames: 'assets/[name]-[hash].[ext]' + } + } : { + // Main process build configuration input: { main: path.resolve(__dirname, 'src/electron/main.ts'), preload: path.resolve(__dirname, 'src/electron/preload.js'), @@ -20,8 +31,8 @@ export default defineConfig(async () => { assetFileNames: 'assets/[name].[ext]', }, }, - target: 'node18', - minify: false, + target: isWebBuild ? 'esnext' : 'node18', + minify: !isWebBuild, sourcemap: true, }, resolve: {