Browse Source

WIP: BROKEN FOR ELECTRON: Fixes in progress

pull/137/head
Matthew Raymer 1 week ago
parent
commit
229d9184b2
  1. 101
      -1748433586226.log
  2. 446
      package-lock.json
  3. 270
      scripts/build-electron.js
  4. 5
      src/db-sql/migration.ts
  5. 86
      src/db/databaseUtil.ts
  6. 31
      src/electron/preload.js
  7. 37
      src/interfaces/common.ts
  8. 18
      src/libs/crypto/vc/passkeyDidPeer.ts
  9. 166
      src/libs/endorserServer.ts
  10. 27
      src/libs/util.ts
  11. 6
      src/main.common.ts
  12. 12
      src/main.electron.ts
  13. 18
      src/main.web.ts
  14. 4
      src/services/AbsurdSqlDatabaseService.ts
  15. 13
      src/services/QRScanner/CapacitorQRScanner.ts
  16. 5
      src/services/QRScanner/WebInlineQRScanner.ts
  17. 2
      src/services/deepLinks.ts
  18. 6
      src/utils/logger.ts
  19. 4
      src/views/ContactsView.vue
  20. 3
      src/views/ImportAccountView.vue

101
-1748433586226.log

@ -0,0 +1,101 @@
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 (<anonymous>)
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 (<anonymous>)
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 (<anonymous>)
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.<computed> @ 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.<computed> @ 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.<computed> @ 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.<computed> @ main.common-DiOUyXe7.js:2103
(anonymous) @ main.common-DiOUyXe7.js:2098
dJ @ main.common-DiOUyXe7.js:2295

446
package-lock.json

@ -205,9 +205,9 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.27.2",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz",
"integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz",
"integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==",
"devOptional": true,
"license": "MIT",
"engines": {
@ -215,22 +215,22 @@
}
},
"node_modules/@babel/core": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz",
"integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.3.tgz",
"integrity": "sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.27.1",
"@babel/helper-compilation-targets": "^7.27.1",
"@babel/helper-module-transforms": "^7.27.1",
"@babel/helpers": "^7.27.1",
"@babel/parser": "^7.27.1",
"@babel/template": "^7.27.1",
"@babel/traverse": "^7.27.1",
"@babel/types": "^7.27.1",
"@babel/generator": "^7.27.3",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-module-transforms": "^7.27.3",
"@babel/helpers": "^7.27.3",
"@babel/parser": "^7.27.3",
"@babel/template": "^7.27.2",
"@babel/traverse": "^7.27.3",
"@babel/types": "^7.27.3",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@ -256,14 +256,14 @@
}
},
"node_modules/@babel/generator": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz",
"integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz",
"integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.27.1",
"@babel/types": "^7.27.1",
"@babel/parser": "^7.27.3",
"@babel/types": "^7.27.3",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
@ -273,13 +273,13 @@
}
},
"node_modules/@babel/helper-annotate-as-pure": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz",
"integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
"integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.27.1"
"@babel/types": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
@ -435,15 +435,15 @@
}
},
"node_modules/@babel/helper-module-transforms": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz",
"integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
"integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1",
"@babel/traverse": "^7.27.1"
"@babel/traverse": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
@ -569,14 +569,14 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz",
"integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.3.tgz",
"integrity": "sha512-h/eKy9agOya1IGuLaZ9tEUgz+uIRXcbtOhRtUyyMf8JFmn1iT13vnl/IGVWSkdOCG/pC57U4S1jnAabAavTMwg==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.27.1",
"@babel/types": "^7.27.1"
"@babel/template": "^7.27.2",
"@babel/types": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
@ -685,12 +685,12 @@
}
},
"node_modules/@babel/parser": {
"version": "7.27.2",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz",
"integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.3.tgz",
"integrity": "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==",
"license": "MIT",
"dependencies": {
"@babel/types": "^7.27.1"
"@babel/types": "^7.27.3"
},
"bin": {
"parser": "bin/babel-parser.js"
@ -1285,9 +1285,9 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz",
"integrity": "sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.3.tgz",
"integrity": "sha512-+F8CnfhuLhwUACIJMLWnjz6zvzYM2r0yeIHKlbgfw7ml8rOMJsXNXV/hyRcb3nb493gRs4WvYpQAndWj/qQmkQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
@ -1383,9 +1383,9 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz",
"integrity": "sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.3.tgz",
"integrity": "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA==",
"devOptional": true,
"license": "MIT",
"dependencies": {
@ -1749,15 +1749,15 @@
}
},
"node_modules/@babel/plugin-transform-object-rest-spread": {
"version": "7.27.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz",
"integrity": "sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.3.tgz",
"integrity": "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/plugin-transform-destructuring": "^7.27.1",
"@babel/plugin-transform-destructuring": "^7.27.3",
"@babel/plugin-transform-parameters": "^7.27.1"
},
"engines": {
@ -2041,9 +2041,9 @@
}
},
"node_modules/@babel/plugin-transform-runtime": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.1.tgz",
"integrity": "sha512-TqGF3desVsTcp3WrJGj4HfKokfCXCLcHpt4PJF0D8/iT6LPd9RS82Upw3KPeyr6B22Lfd3DO8MVrmp0oRkUDdw==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.3.tgz",
"integrity": "sha512-bA9ZL5PW90YwNgGfjg6U+7Qh/k3zCEQJ06BFgAGRp/yMjw9hP9UGbGPtx3KSOkHGljEPCCxaE+PH4fUR2h1sDw==",
"license": "MIT",
"optional": true,
"peer": true,
@ -2395,9 +2395,9 @@
}
},
"node_modules/@babel/runtime": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz",
"integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.3.tgz",
"integrity": "sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw==",
"devOptional": true,
"license": "MIT",
"engines": {
@ -2420,17 +2420,17 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz",
"integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.3.tgz",
"integrity": "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.27.1",
"@babel/parser": "^7.27.1",
"@babel/template": "^7.27.1",
"@babel/types": "^7.27.1",
"@babel/generator": "^7.27.3",
"@babel/parser": "^7.27.3",
"@babel/template": "^7.27.2",
"@babel/types": "^7.27.3",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@ -2440,18 +2440,18 @@
},
"node_modules/@babel/traverse--for-generate-function-map": {
"name": "@babel/traverse",
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz",
"integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.3.tgz",
"integrity": "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.27.1",
"@babel/parser": "^7.27.1",
"@babel/template": "^7.27.1",
"@babel/types": "^7.27.1",
"@babel/generator": "^7.27.3",
"@babel/parser": "^7.27.3",
"@babel/template": "^7.27.2",
"@babel/types": "^7.27.3",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@ -2481,9 +2481,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
"integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz",
"integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
@ -8189,13 +8189,12 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz",
"integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==",
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz",
"integrity": "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -8203,13 +8202,12 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz",
"integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==",
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz",
"integrity": "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -8273,13 +8271,12 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz",
"integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==",
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz",
"integrity": "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -8287,13 +8284,12 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz",
"integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==",
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz",
"integrity": "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -8371,13 +8367,12 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz",
"integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==",
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz",
"integrity": "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -8385,13 +8380,12 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz",
"integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==",
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz",
"integrity": "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -8399,13 +8393,12 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz",
"integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==",
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz",
"integrity": "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -8427,13 +8420,12 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz",
"integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==",
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz",
"integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@ -8848,110 +8840,6 @@
"@rollup/rollup-win32-x64-msvc": "4.34.9"
}
},
"node_modules/@stencil/core/node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz",
"integrity": "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@stencil/core/node_modules/@rollup/rollup-darwin-x64": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz",
"integrity": "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@stencil/core/node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz",
"integrity": "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@stencil/core/node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz",
"integrity": "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@stencil/core/node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz",
"integrity": "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@stencil/core/node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz",
"integrity": "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@stencil/core/node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz",
"integrity": "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@stencil/core/node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.34.9",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz",
"integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@surma/rollup-plugin-off-main-thread": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
@ -9556,9 +9444,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "20.17.50",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.50.tgz",
"integrity": "sha512-Mxiq0ULv/zo1OzOhwPqOA13I81CV/W3nvd3ChtQZRT5Cwz3cr0FKo/wMSsbTqL3EXpaBAEQhva2B8ByRkOIh9A==",
"version": "20.17.51",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.51.tgz",
"integrity": "sha512-hccptBl7C8lHiKxTBsY6vYYmqpmw1E/aGR/8fmueE+B390L3pdMOpNSRvFO4ZnXzW5+p2HBXV0yNABd2vdk22Q==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.2"
@ -15403,9 +15291,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.158",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.158.tgz",
"integrity": "sha512-9vcp2xHhkvraY6AHw2WMi+GDSLPX42qe2xjYaVoZqFRJiOcilVQFq9mZmpuHEQpzlgGDelKlV7ZiGcmMsc8WxQ==",
"version": "1.5.159",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.159.tgz",
"integrity": "sha512-CEvHptWAMV5p6GJ0Lq8aheyvVbfzVrv5mmidu1D3pidoVNkB3tTBsTMVtPJ+rzRK5oV229mCLz9Zj/hNvU8GBA==",
"devOptional": true,
"license": "ISC"
},
@ -16787,9 +16675,9 @@
}
},
"node_modules/fdir": {
"version": "6.4.4",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
"version": "6.4.5",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz",
"integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==",
"dev": true,
"license": "MIT",
"peerDependencies": {
@ -26161,6 +26049,118 @@
"fsevents": "~2.3.2"
}
},
"node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz",
"integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/rollup/node_modules/@rollup/rollup-darwin-x64": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz",
"integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz",
"integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz",
"integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz",
"integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz",
"integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/rollup/node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz",
"integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/rollup/node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz",
"integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/run-con": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/run-con/-/run-con-1.3.2.tgz",
@ -28355,9 +28355,9 @@
}
},
"node_modules/terser": {
"version": "5.39.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.39.2.tgz",
"integrity": "sha512-yEPUmWve+VA78bI71BW70Dh0TuV4HHd+I5SHOAfS1+QBOmvmCiiffgjR8ryyEd3KIfvPGFqoADt8LdQ6XpXIvg==",
"version": "5.40.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.40.0.tgz",
"integrity": "sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA==",
"devOptional": true,
"license": "BSD-2-Clause",
"dependencies": {
@ -29498,9 +29498,9 @@
}
},
"node_modules/validator": {
"version": "13.15.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz",
"integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==",
"version": "13.15.15",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz",
"integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
@ -30947,9 +30947,9 @@
}
},
"node_modules/zod": {
"version": "3.25.30",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.30.tgz",
"integrity": "sha512-VolhdEtu6TJr/fzGuHA/SZ5ixvXqA6ADOG9VRcQ3rdOKmF5hkmcJbyaQjUH5BgmpA9gej++zYRX7zjSmdReIwA==",
"version": "3.25.32",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.32.tgz",
"integrity": "sha512-OSm2xTIRfW8CV5/QKgngwmQW/8aPfGdaQFlrGoErlgg/Epm7cjb6K6VEyExfe65a3VybUOnu381edLb0dfJl0g==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"

270
scripts/build-electron.js

@ -4,7 +4,6 @@ const path = require('path');
console.log('Starting electron build process...');
// Define paths
const webDistPath = path.join(__dirname, '..', 'dist');
const electronDistPath = path.join(__dirname, '..', 'dist-electron');
const wwwPath = path.join(electronDistPath, 'www');
@ -13,8 +12,48 @@ if (!fs.existsSync(wwwPath)) {
fs.mkdirSync(wwwPath, { recursive: true });
}
// Copy web files to www directory
fs.cpSync(webDistPath, wwwPath, { recursive: true });
// Create a platform-specific index.html for Electron
const initialIndexContent = `<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">
<link rel="icon" href="/favicon.ico">
<title>TimeSafari</title>
</head>
<body>
<noscript>
<strong>We're sorry but TimeSafari doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script type="module">
// Force electron platform
window.process = { env: { VITE_PLATFORM: 'electron' } };
import('./src/main.electron.ts');
</script>
</body>
</html>`;
// Write the Electron-specific index.html
fs.writeFileSync(path.join(wwwPath, 'index.html'), initialIndexContent);
// Copy only necessary assets from web build
const webDistPath = path.join(__dirname, '..', 'dist');
if (fs.existsSync(webDistPath)) {
// Copy assets directory
const assetsSrc = path.join(webDistPath, 'assets');
const assetsDest = path.join(wwwPath, 'assets');
if (fs.existsSync(assetsSrc)) {
fs.cpSync(assetsSrc, assetsDest, { recursive: true });
}
// Copy favicon
const faviconSrc = path.join(webDistPath, 'favicon.ico');
if (fs.existsSync(faviconSrc)) {
fs.copyFileSync(faviconSrc, path.join(wwwPath, 'favicon.ico'));
}
}
// Remove service worker files
const swFilesToRemove = [
@ -88,13 +127,13 @@ if (fs.existsSync(indexPath)) {
// Fix asset paths
console.log('Fixing asset paths in index.html...');
let indexContent = fs.readFileSync(indexPath, 'utf8');
indexContent = indexContent
let modifiedIndexContent = fs.readFileSync(indexPath, 'utf8');
modifiedIndexContent = modifiedIndexContent
.replace(/\/assets\//g, './assets/')
.replace(/href="\//g, 'href="./')
.replace(/src="\//g, 'src="./');
fs.writeFileSync(indexPath, indexContent);
fs.writeFileSync(indexPath, modifiedIndexContent);
// Verify no service worker references remain
const finalContent = fs.readFileSync(indexPath, 'utf8');
@ -103,215 +142,24 @@ if (finalContent.includes('serviceWorker') || finalContent.includes('workbox'))
}
// Check for remaining /assets/ paths
console.log('After path fixing, checking for remaining /assets/ paths:', indexContent.includes('/assets/'));
console.log('Sample of fixed content:', indexContent.substring(0, 500));
console.log('After path fixing, checking for remaining /assets/ paths:', finalContent.includes('/assets/'));
console.log('Sample of fixed content:', finalContent.substring(0, 500));
console.log('Copied and fixed web files in:', wwwPath);
// Copy main process files
console.log('Copying main process files...');
// Create the main process file with inlined logger
const mainContent = `const { app, BrowserWindow } = require("electron");
const path = require("path");
const fs = require("fs");
// Copy main process files
console.log('Copying main process files...');
// Inline logger implementation
const logger = {
log: (...args) => console.log(...args),
error: (...args) => console.error(...args),
info: (...args) => console.info(...args),
warn: (...args) => console.warn(...args),
debug: (...args) => console.debug(...args),
};
// Copy the main process file instead of creating a template
const mainSrcPath = path.join(__dirname, '..', 'dist-electron', 'main.js');
const mainDestPath = path.join(electronDistPath, 'main.js');
// Check if running in dev mode
const isDev = process.argv.includes("--inspect");
function createWindow() {
// Add before createWindow function
const preloadPath = path.join(__dirname, "preload.js");
logger.log("Checking preload path:", preloadPath);
logger.log("Preload exists:", fs.existsSync(preloadPath));
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
webSecurity: true,
allowRunningInsecureContent: false,
preload: path.join(__dirname, "preload.js"),
},
});
// Always open DevTools for now
mainWindow.webContents.openDevTools();
// Intercept requests to fix asset paths
mainWindow.webContents.session.webRequest.onBeforeRequest(
{
urls: [
"file://*/*/assets/*",
"file://*/assets/*",
"file:///assets/*", // Catch absolute paths
"<all_urls>", // Catch all URLs as a fallback
],
},
(details, callback) => {
let url = details.url;
// Handle paths that don't start with file://
if (!url.startsWith("file://") && url.includes("/assets/")) {
url = \`file://\${path.join(__dirname, "www", url)}\`;
}
// Handle absolute paths starting with /assets/
if (url.includes("/assets/") && !url.includes("/www/assets/")) {
const baseDir = url.includes("dist-electron")
? url.substring(
0,
url.indexOf("/dist-electron") + "/dist-electron".length,
)
: \`file://\${__dirname}\`;
const assetPath = url.split("/assets/")[1];
const newUrl = \`\${baseDir}/www/assets/\${assetPath}\`;
callback({ redirectURL: newUrl });
return;
}
callback({}); // No redirect for other URLs
},
);
if (isDev) {
// Debug info
logger.log("Debug Info:");
logger.log("Running in dev mode:", isDev);
logger.log("App is packaged:", app.isPackaged);
logger.log("Process resource path:", process.resourcesPath);
logger.log("App path:", app.getAppPath());
logger.log("__dirname:", __dirname);
logger.log("process.cwd():", process.cwd());
}
const indexPath = path.join(__dirname, "www", "index.html");
if (isDev) {
logger.log("Loading index from:", indexPath);
logger.log("www path:", path.join(__dirname, "www"));
logger.log("www assets path:", path.join(__dirname, "www", "assets"));
}
if (!fs.existsSync(indexPath)) {
logger.error(\`Index file not found at: \${indexPath}\`);
throw new Error("Index file not found");
}
// Add CSP headers to allow API connections, Google Fonts, and zxing-wasm
mainWindow.webContents.session.webRequest.onHeadersReceived(
(details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
"Content-Security-Policy": [
"default-src 'self';" +
"connect-src 'self' https://api.endorser.ch https://*.timesafari.app https://*.jsdelivr.net;" +
"img-src 'self' data: https: blob:;" +
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.jsdelivr.net;" +
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;" +
"font-src 'self' data: https://fonts.gstatic.com;" +
"style-src-elem 'self' 'unsafe-inline' https://fonts.googleapis.com;" +
"worker-src 'self' blob:;",
],
},
});
},
);
// Load the index.html
mainWindow
.loadFile(indexPath)
.then(() => {
logger.log("Successfully loaded index.html");
if (isDev) {
mainWindow.webContents.openDevTools();
logger.log("DevTools opened - running in dev mode");
}
})
.catch((err) => {
logger.error("Failed to load index.html:", err);
logger.error("Attempted path:", indexPath);
});
// Listen for console messages from the renderer
mainWindow.webContents.on("console-message", (_event, _level, message) => {
logger.log("Renderer Console:", message);
});
// Add right after creating the BrowserWindow
mainWindow.webContents.on(
"did-fail-load",
(_event, errorCode, errorDescription) => {
logger.error("Page failed to load:", errorCode, errorDescription);
},
);
mainWindow.webContents.on("preload-error", (_event, preloadPath, error) => {
logger.error("Preload script error:", preloadPath, error);
});
mainWindow.webContents.on(
"console-message",
(_event, _level, message, line, sourceId) => {
logger.log("Renderer Console:", line, sourceId, message);
},
);
// Enable remote debugging when in dev mode
if (isDev) {
mainWindow.webContents.openDevTools();
}
if (fs.existsSync(mainSrcPath)) {
fs.copyFileSync(mainSrcPath, mainDestPath);
console.log('Copied main process file successfully');
} else {
console.error('Main process file not found at:', mainSrcPath);
process.exit(1);
}
// Handle app ready
app.whenReady().then(createWindow);
// Handle all windows closed
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// Handle any errors
process.on("uncaughtException", (error) => {
logger.error("Uncaught Exception:", error);
});
`;
// Write the main process file
const mainDest = path.join(electronDistPath, 'main.js');
fs.writeFileSync(mainDest, mainContent);
// Copy preload script if it exists
const preloadSrc = path.join(__dirname, '..', 'src', 'electron', 'preload.js');
const preloadDest = path.join(electronDistPath, 'preload.js');
if (fs.existsSync(preloadSrc)) {
console.log(`Copying ${preloadSrc} to ${preloadDest}`);
fs.copyFileSync(preloadSrc, preloadDest);
}
// Verify build structure
console.log('\nVerifying build structure:');
console.log('Files in dist-electron:', fs.readdirSync(electronDistPath));
console.log('Build completed successfully!');
console.log('Electron build process completed successfully');

5
src/db-sql/migration.ts

@ -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);

86
src/db/databaseUtil.ts

@ -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);
}
}

31
src/electron/preload.js

@ -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);
}

37
src/interfaces/common.ts

@ -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;
};

18
src/libs/crypto/vc/passkeyDidPeer.ts

@ -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);
}

166
src/libs/endorserServer.ts

@ -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;
}
@ -572,20 +573,25 @@ export function errorStringForLog(error: unknown) {
}
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) {
@ -685,7 +691,7 @@ export function hydrateGive(
"@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"
"@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,8 +1359,8 @@ 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 vcJwt = await createInviteJwt(activeDid, contact);
const url = apiServer + "/api/v2/claim";
const resp = await axios.post<{
success?: {
handleId?: string;
@ -1344,23 +1370,27 @@ export async function register(
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
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));

27
src/libs/util.ts

@ -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;
};

6
src/main.common.ts

@ -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");

12
src/main.electron.ts

@ -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");

18
src/main.web.ts

@ -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");

4
src/services/AbsurdSqlDatabaseService.ts

@ -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() {

13
src/services/QRScanner/CapacitorQRScanner.ts

@ -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");
}

5
src/services/QRScanner/WebInlineQRScanner.ts

@ -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(

2
src/services/deepLinks.ts

@ -124,7 +124,7 @@ export class DeepLinkHandler {
throw {
code: "INVALID_ROUTE",
message: `Invalid route path: ${routePath}`,
details: { routePath }
details: { routePath },
};
}

6
src/utils/logger.ts

@ -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);

4
src/views/ContactsView.vue

@ -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

3
src/views/ImportAccountView.vue

@ -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";

Loading…
Cancel
Save