Browse Source

WIP: Fix Electron build issues and migrate to @nostr/tools

- Fix TypeScript compilation errors in platform services
- Add missing rotateCamera method and isNativeApp property
- Fix index.html path resolution for packaged Electron apps
- Create separate Vite config for Electron renderer process
- Migrate from nostr-tools to @nostr/tools via JSR for ESM compatibility
- Update all Vite configs to handle mixed npm/JSR package management
- Add comprehensive documentation in BUILDING.md
- Fix preload script path resolution in packaged builds

Resolves build failures with deep imports and missing UI in AppImage.
streamline-attempt
Matthew Raymer 1 week ago
parent
commit
dc1fa14095
  1. 15
      -1750838135249.log
  2. 4
      -1750838461020.log
  3. 1
      .npmrc
  4. 83
      BUILDING.md
  5. 232
      package-lock.json
  6. 5
      package.json
  7. 8
      scripts/build-electron.js
  8. 29
      src/electron/main.ts
  9. 2
      src/interfaces/common.ts
  10. 10
      src/services/platforms/ElectronPlatformService.ts
  11. 10
      src/services/platforms/WebPlatformService.ts
  12. 1
      src/test/index.ts
  13. 1
      src/views/HomeView.vue
  14. 10
      src/views/NewEditProjectView.vue
  15. 18
      vite.config.common.mts
  16. 25
      vite.config.electron.renderer.mts
  17. 9
      vite.config.mts
  18. 9
      vite.config.ts

15
-1750838135249.log

@ -0,0 +1,15 @@
VM4 sandbox_bundle:2 Unable to load preload script: /home/noone/projects/timesafari/crowd-master/preload.js
(anonymous) @ VM4 sandbox_bundle:2
VM4 sandbox_bundle:2 Error: ENOENT: no such file or directory, open '/home/noone/projects/timesafari/crowd-master/preload.js'
at async open (node:internal/fs/promises:639:25)
at async Object.readFile (node:internal/fs/promises:1246:14)
at async node:electron/js2c/browser_init:2:108714
at async Promise.all (index 0)
at async node:electron/js2c/browser_init:2:108650
at async IpcMainImpl.<anonymous> (node:electron/js2c/browser_init:2:105615)
(anonymous) @ VM4 sandbox_bundle:2
main.electron.ts:1
Failed to load resource: net::ERR_FILE_NOT_FOUND
index.html:1 Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: file:///tmp/.mount_TimeSaGVOt4a/resources/app.asar/dist-electron/www/src/main.electron.ts

4
-1750838461020.log

@ -0,0 +1,4 @@
main.electron.js:1
Failed to load resource: net::ERR_FILE_NOT_FOUND

1
.npmrc

@ -0,0 +1 @@
@jsr:registry=https://npm.jsr.io

83
BUILDING.md

@ -81,6 +81,89 @@ Install dependencies:
npm install npm install
``` ```
## Package Management
TimeSafari uses a mixed package management approach, combining npm and JSR (JavaScript Registry) for optimal dependency management.
### JSR Integration
Some packages are installed via JSR for better ESM support and modern TypeScript compatibility:
```bash
# Install JSR packages
npx jsr add @nostr/tools
```
### Package Migration History
#### nostr-tools → @nostr/tools
**Date**: June 2025
**Reason**: Resolved Vite/Rollup build issues with deep imports
**Before** (npm):
```typescript
import { finalizeEvent } from "nostr-tools/lib/cjs/index.js";
import { accountFromExtendedKey } from "nostr-tools/lib/cjs/nip06.js";
```
**After** (JSR):
```typescript
import { finalizeEvent } from "@nostr/tools";
import { accountFromExtendedKey } from "@nostr/tools/nip06";
```
**Benefits**:
- ✅ Proper ESM support
- ✅ No deep import issues with Vite/Rollup
- ✅ Better TypeScript compatibility
- ✅ Modern package structure
### Current Package Strategy
- **npm**: Primary package manager for most dependencies
- **JSR**: Used for packages with better ESM support or modern alternatives
- **Mixed approach**: Allows using the best package for each dependency
### When to Use JSR
Consider using JSR for:
- Packages with ESM/CJS compatibility issues in npm
- Modern TypeScript-first packages
- Packages that work better with modern bundlers
- New dependencies where JSR has a better alternative
### Vite Configuration
The build system is configured to handle both npm and JSR packages:
```typescript
// vite.config.common.mts
resolve: {
alias: {
'@nostr/tools': path.resolve(__dirname, 'node_modules/@nostr/tools'),
'@nostr/tools/nip06': path.resolve(__dirname, 'node_modules/@nostr/tools/nip06'),
}
}
```
### Troubleshooting Package Issues
1. **Build failures with deep imports**
- Check if package has ESM/CJS compatibility issues
- Consider JSR alternative if available
- Update Vite configuration if needed
2. **TypeScript errors**
- Ensure proper type definitions are available
- Check package exports in package.json
- Verify import paths match package structure
3. **Mixed package manager issues**
- Keep package.json and node_modules in sync
- Use `npm install` after JSR package additions
- Check for conflicting package versions
## Web Development ## Web Development
### Local Development ### Local Development

232
package-lock.json

@ -27,6 +27,7 @@
"@fortawesome/free-solid-svg-icons": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/vue-fontawesome": "^3.0.6", "@fortawesome/vue-fontawesome": "^3.0.6",
"@jlongster/sql.js": "^1.6.7", "@jlongster/sql.js": "^1.6.7",
"@nostr/tools": "npm:@jsr/nostr__tools@^2.15.0",
"@peculiar/asn1-ecc": "^2.3.8", "@peculiar/asn1-ecc": "^2.3.8",
"@peculiar/asn1-schema": "^2.3.8", "@peculiar/asn1-schema": "^2.3.8",
"@pvermeer/dexie-encrypted-addon": "^3.0.0", "@pvermeer/dexie-encrypted-addon": "^3.0.0",
@ -66,7 +67,6 @@
"lru-cache": "^10.2.0", "lru-cache": "^10.2.0",
"luxon": "^3.4.4", "luxon": "^3.4.4",
"merkletreejs": "^0.3.11", "merkletreejs": "^0.3.11",
"nostr-tools": "^2.10.4",
"notiwind": "^2.0.2", "notiwind": "^2.0.2",
"papaparse": "^5.4.1", "papaparse": "^5.4.1",
"pina": "^0.20.2204228", "pina": "^0.20.2204228",
@ -7635,6 +7635,117 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@nostr/tools": {
"name": "@jsr/nostr__tools",
"version": "2.15.0",
"resolved": "https://npm.jsr.io/~/11/@jsr/nostr__tools/2.15.0.tgz",
"integrity": "sha512-ZbnkPKuWAUdEE8zxyZt7LfyWSDLG58XLtfZ9QJD9MkPIyyt/YJ6DQ5W0S+PX5qQw48Nz+gCUkC15eiHMwp1ccA==",
"dependencies": {
"@noble/ciphers": "^0.5.1",
"@noble/curves": "1.2.0",
"@noble/hashes": "1.3.1",
"@scure/base": "1.1.1",
"@scure/bip32": "1.3.1",
"@scure/bip39": "1.2.1",
"nostr-wasm": "0.1.0"
}
},
"node_modules/@nostr/tools/node_modules/@noble/ciphers": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.5.3.tgz",
"integrity": "sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==",
"license": "MIT",
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@nostr/tools/node_modules/@noble/curves": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "1.3.2"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@nostr/tools/node_modules/@noble/curves/node_modules/@noble/hashes": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
"license": "MIT",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@nostr/tools/node_modules/@noble/hashes": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
"license": "MIT",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@nostr/tools/node_modules/@scure/base": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"license": "MIT"
},
"node_modules/@nostr/tools/node_modules/@scure/bip32": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz",
"integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
"license": "MIT",
"dependencies": {
"@noble/curves": "~1.1.0",
"@noble/hashes": "~1.3.1",
"@scure/base": "~1.1.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@nostr/tools/node_modules/@scure/bip32/node_modules/@noble/curves": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "1.3.1"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@nostr/tools/node_modules/@scure/bip39": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
"integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "~1.3.0",
"@scure/base": "~1.1.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@npmcli/fs": { "node_modules/@npmcli/fs": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
@ -23209,125 +23320,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/nostr-tools": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.15.0.tgz",
"integrity": "sha512-Jj/+UFbu3JbTAWP4ipPFNuyD4W5eVRBNAP+kmnoRCYp3bLmTrlQ0Qhs5O1xSQJTFpjdZqoS0zZOUKdxUdjc+pw==",
"license": "Unlicense",
"dependencies": {
"@noble/ciphers": "^0.5.1",
"@noble/curves": "1.2.0",
"@noble/hashes": "1.3.1",
"@scure/base": "1.1.1",
"@scure/bip32": "1.3.1",
"@scure/bip39": "1.2.1",
"nostr-wasm": "0.1.0"
},
"peerDependencies": {
"typescript": ">=5.0.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/nostr-tools/node_modules/@noble/ciphers": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.5.3.tgz",
"integrity": "sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==",
"license": "MIT",
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-tools/node_modules/@noble/curves": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "1.3.2"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
"license": "MIT",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-tools/node_modules/@noble/hashes": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
"license": "MIT",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-tools/node_modules/@scure/base": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"license": "MIT"
},
"node_modules/nostr-tools/node_modules/@scure/bip32": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz",
"integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
"license": "MIT",
"dependencies": {
"@noble/curves": "~1.1.0",
"@noble/hashes": "~1.3.1",
"@scure/base": "~1.1.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-tools/node_modules/@scure/bip32/node_modules/@noble/curves": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "1.3.1"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-tools/node_modules/@scure/bip39": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
"integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "~1.3.0",
"@scure/base": "~1.1.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-wasm": { "node_modules/nostr-wasm": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.1.0.tgz", "resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.1.0.tgz",

5
package.json

@ -21,7 +21,8 @@
"check:android-device": "adb devices | grep -w 'device' || (echo 'No Android device connected' && exit 1)", "check:android-device": "adb devices | grep -w 'device' || (echo 'No Android device connected' && exit 1)",
"check:ios-device": "xcrun xctrace list devices 2>&1 | grep -w 'Booted' || (echo 'No iOS simulator running' && exit 1)", "check:ios-device": "xcrun xctrace list devices 2>&1 | grep -w 'Booted' || (echo 'No iOS simulator running' && exit 1)",
"clean:electron": "rimraf dist-electron", "clean:electron": "rimraf dist-electron",
"build:electron": "./scripts/build-electron.sh", "build:electron": "./scripts/build-electron.sh && npm run build:electron-renderer",
"build:electron-renderer": "vite build --config vite.config.electron.renderer.mts",
"build:capacitor": "vite build --mode capacitor --config vite.config.capacitor.mts", "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": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build --config vite.config.web.mts",
"electron:dev": "./scripts/electron-dev.sh", "electron:dev": "./scripts/electron-dev.sh",
@ -59,6 +60,7 @@
"@fortawesome/free-solid-svg-icons": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/vue-fontawesome": "^3.0.6", "@fortawesome/vue-fontawesome": "^3.0.6",
"@jlongster/sql.js": "^1.6.7", "@jlongster/sql.js": "^1.6.7",
"@nostr/tools": "npm:@jsr/nostr__tools@^2.15.0",
"@peculiar/asn1-ecc": "^2.3.8", "@peculiar/asn1-ecc": "^2.3.8",
"@peculiar/asn1-schema": "^2.3.8", "@peculiar/asn1-schema": "^2.3.8",
"@pvermeer/dexie-encrypted-addon": "^3.0.0", "@pvermeer/dexie-encrypted-addon": "^3.0.0",
@ -98,7 +100,6 @@
"lru-cache": "^10.2.0", "lru-cache": "^10.2.0",
"luxon": "^3.4.4", "luxon": "^3.4.4",
"merkletreejs": "^0.3.11", "merkletreejs": "^0.3.11",
"nostr-tools": "^2.10.4",
"notiwind": "^2.0.2", "notiwind": "^2.0.2",
"papaparse": "^5.4.1", "papaparse": "^5.4.1",
"pina": "^0.20.2204228", "pina": "^0.20.2204228",

8
scripts/build-electron.js

@ -19,7 +19,7 @@ const initialIndexContent = `<!DOCTYPE html>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover"> <meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="./favicon.ico">
<title>TimeSafari</title> <title>TimeSafari</title>
</head> </head>
<body> <body>
@ -27,11 +27,7 @@ const initialIndexContent = `<!DOCTYPE html>
<strong>We're sorry but TimeSafari doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> <strong>We're sorry but TimeSafari doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript> </noscript>
<div id="app"></div> <div id="app"></div>
<script type="module"> <script type="module" src="./main.electron.js"></script>
// Force electron platform
window.process = { env: { VITE_PLATFORM: 'electron' } };
import('./src/main.electron.ts');
</script>
</body> </body>
</html>`; </html>`;

29
src/electron/main.ts

@ -21,7 +21,9 @@ const isDev = process.argv.includes("--inspect");
function createWindow(): void { function createWindow(): void {
// Add before createWindow function // Add before createWindow function
const preloadPath = path.join(__dirname, "preload.js"); const preloadPath = app.isPackaged
? path.join(app.getAppPath(), "dist-electron", "preload.js")
: path.join(__dirname, "preload.js");
logger.log("Checking preload path:", preloadPath); logger.log("Checking preload path:", preloadPath);
logger.log("Preload exists:", fs.existsSync(preloadPath)); logger.log("Preload exists:", fs.existsSync(preloadPath));
@ -53,7 +55,7 @@ function createWindow(): void {
contextIsolation: true, contextIsolation: true,
webSecurity: true, webSecurity: true,
allowRunningInsecureContent: false, allowRunningInsecureContent: false,
preload: path.join(__dirname, "preload.js"), preload: preloadPath,
}, },
}); });
@ -107,15 +109,27 @@ function createWindow(): void {
logger.log("process.cwd():", process.cwd()); logger.log("process.cwd():", process.cwd());
} }
let indexPath = path.resolve(__dirname, "dist-electron", "www", "index.html"); let indexPath: string;
if (!fs.existsSync(indexPath)) { if (app.isPackaged) {
// Fallback for dev mode indexPath = path.join(
app.getAppPath(),
"dist-electron",
"www",
"index.html",
);
logger.log("[main.ts] Using packaged indexPath:", indexPath);
} else {
indexPath = path.resolve( indexPath = path.resolve(
process.cwd(), process.cwd(),
"dist-electron", "dist-electron",
"www", "www",
"index.html", "index.html",
); );
logger.log("[main.ts] Using dev indexPath:", indexPath);
if (!fs.existsSync(indexPath)) {
logger.error("[main.ts] Dev index.html not found:", indexPath);
throw new Error("Index file not found");
}
} }
if (isDev) { if (isDev) {
@ -124,11 +138,6 @@ function createWindow(): void {
logger.log("www assets path:", path.join(__dirname, "www", "assets")); 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 // Add CSP headers to allow API connections
mainWindow.webContents.session.webRequest.onHeadersReceived( mainWindow.webContents.session.webRequest.onHeadersReceived(
(details, callback) => { (details, callback) => {

2
src/interfaces/common.ts

@ -4,7 +4,7 @@ export interface GenericVerifiableCredential {
"@type": string; "@type": string;
name?: string; name?: string;
description?: string; description?: string;
agent?: string; agent?: string | { identifier: string };
[key: string]: unknown; [key: string]: unknown;
} }

10
src/services/platforms/ElectronPlatformService.ts

@ -205,6 +205,7 @@ export class ElectronPlatformService implements PlatformService {
isIOS: false, isIOS: false,
hasFileDownload: false, // Not implemented yet hasFileDownload: false, // Not implemented yet
needsFileHandlingInstructions: false, needsFileHandlingInstructions: false,
isNativeApp: true, // Electron is a native app
}; };
} }
@ -345,4 +346,13 @@ export class ElectronPlatformService implements PlatformService {
); );
} }
} }
/**
* Rotates the camera between front and back cameras.
* @returns Promise that resolves when the camera is rotated
* @throws Error indicating camera rotation is not implemented in Electron
*/
async rotateCamera(): Promise<void> {
throw new Error("Camera rotation not implemented in Electron platform");
}
} }

10
src/services/platforms/WebPlatformService.ts

@ -33,6 +33,7 @@ export class WebPlatformService implements PlatformService {
isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent), isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent),
hasFileDownload: true, hasFileDownload: true,
needsFileHandlingInstructions: false, needsFileHandlingInstructions: false,
isNativeApp: false, // Web is not a native app
}; };
} }
@ -382,4 +383,13 @@ export class WebPlatformService implements PlatformService {
.query(sql, params) .query(sql, params)
.then((result: QueryExecResult[]) => result[0]?.values[0]); .then((result: QueryExecResult[]) => result[0]?.values[0]);
} }
/**
* Rotates the camera between front and back cameras.
* @returns Promise that resolves when the camera is rotated
* @throws Error indicating camera rotation is not implemented in web platform
*/
async rotateCamera(): Promise<void> {
throw new Error("Camera rotation not implemented in web platform");
}
} }

1
src/test/index.ts

@ -4,6 +4,7 @@ import * as databaseUtil from "../db/databaseUtil";
import { SERVICE_ID } from "../libs/endorserServer"; import { SERVICE_ID } from "../libs/endorserServer";
import { deriveAddress, newIdentifier } from "../libs/crypto"; import { deriveAddress, newIdentifier } from "../libs/crypto";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { AppString } from "../constants/app";
/** /**
* Get User #0 to sign & submit a RegisterAction for the user's activeDid. * Get User #0 to sign & submit a RegisterAction for the user's activeDid.
*/ */

1
src/views/HomeView.vue

@ -345,7 +345,6 @@ import { logger } from "../utils/logger";
import { GiveRecordWithContactInfo } from "../interfaces/give"; import { GiveRecordWithContactInfo } from "../interfaces/give";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import * as Package from "../../package.json"; import * as Package from "../../package.json";
import { id_ce_authorityKeyIdentifier } from "node_modules/@simplewebauthn/server/esm/deps";
interface Claim { interface Claim {
claim?: Claim; // For nested claims in Verifiable Credentials claim?: Claim; // For nested claims in Verifiable Credentials

10
src/views/NewEditProjectView.vue

@ -217,11 +217,11 @@
import "leaflet/dist/leaflet.css"; import "leaflet/dist/leaflet.css";
import { AxiosError, AxiosRequestHeaders } from "axios"; import { AxiosError, AxiosRequestHeaders } from "axios";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
import { finalizeEvent } from "nostr-tools/lib/esm/index.js"; import { finalizeEvent } from "@nostr/tools";
import { import {
accountFromExtendedKey, accountFromExtendedKey,
extendedKeysFromSeedWords, extendedKeysFromSeedWords,
} from "nostr-tools/lib/esm/nip06.js"; } from "@nostr/tools/nip06";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet"; import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
import { RouteLocationNormalizedLoaded, Router } from "vue-router"; import { RouteLocationNormalizedLoaded, Router } from "vue-router";
@ -244,12 +244,14 @@ import {
retrieveAccountCount, retrieveAccountCount,
retrieveFullyDecryptedAccount, retrieveFullyDecryptedAccount,
} from "../libs/util"; } from "../libs/util";
import { import {
EventTemplate, EventTemplate,
UnsignedEvent, UnsignedEvent,
VerifiedEvent, VerifiedEvent,
} from "nostr-tools/lib/esm/index.js"; serializeEvent,
import { serializeEvent } from "nostr-tools/lib/esm/index.js"; } from "@nostr/tools";
// @ts-ignore
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@Component({ @Component({
components: { ImageMethodDialog, LMap, LMarker, LTileLayer, QuickNav }, components: { ImageMethodDialog, LMap, LMarker, LTileLayer, QuickNav },

18
vite.config.common.mts

@ -73,28 +73,20 @@ export async function createBuildConfig(mode: string): Promise<UserConfig> {
}, },
resolve: { resolve: {
alias: { alias: {
'@': path.resolve(__dirname, './src'), '@': path.resolve(__dirname, 'src'),
'@nostr/tools': path.resolve(__dirname, 'node_modules/@nostr/tools'),
'@nostr/tools/nip06': path.resolve(__dirname, 'node_modules/@nostr/tools/nip06'),
...appConfig.aliasConfig, ...appConfig.aliasConfig,
'path': path.resolve(__dirname, './src/utils/node-modules/path.js'), 'path': path.resolve(__dirname, './src/utils/node-modules/path.js'),
'fs': path.resolve(__dirname, './src/utils/node-modules/fs.js'), 'fs': path.resolve(__dirname, './src/utils/node-modules/fs.js'),
'crypto': path.resolve(__dirname, './src/utils/node-modules/crypto.js'), 'crypto': path.resolve(__dirname, './src/utils/node-modules/crypto.js'),
'nostr-tools/nip06': mode === 'development'
? 'nostr-tools/nip06'
: path.resolve(__dirname, 'node_modules/nostr-tools/nip06'),
'nostr-tools/core': mode === 'development'
? 'nostr-tools'
: path.resolve(__dirname, 'node_modules/nostr-tools'),
'nostr-tools': path.resolve(__dirname, 'node_modules/nostr-tools'),
'dexie-export-import': path.resolve(__dirname, 'node_modules/dexie-export-import') 'dexie-export-import': path.resolve(__dirname, 'node_modules/dexie-export-import')
} }
}, },
optimizeDeps: { optimizeDeps: {
include: [ include: [
'nostr-tools', '@nostr/tools',
'nostr-tools/nip06', '@nostr/tools/nip06',
'nostr-tools/core',
'dexie-export-import',
'@jlongster/sql.js'
], ],
exclude: isElectron ? [ exclude: isElectron ? [
'register-service-worker', 'register-service-worker',

25
vite.config.electron.renderer.mts

@ -0,0 +1,25 @@
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
build: {
outDir: 'dist-electron/www',
emptyOutDir: false,
rollupOptions: {
input: path.resolve(__dirname, 'src/main.electron.ts'),
output: {
entryFileNames: 'main.electron.js'
}
},
commonjsOptions: {
transformMixedEsModules: true
}
}
});

9
vite.config.mts

@ -9,10 +9,9 @@ export default defineConfig({
plugins: [vue()], plugins: [vue()],
resolve: { resolve: {
alias: { alias: {
'@': path.resolve(__dirname, './src'), '@': path.resolve(__dirname, 'src'),
'nostr-tools': path.resolve(__dirname, 'node_modules/nostr-tools'), '@nostr/tools': path.resolve(__dirname, 'node_modules/@nostr/tools'),
'nostr-tools/nip06': path.resolve(__dirname, 'node_modules/nostr-tools/nip06'), '@nostr/tools/nip06': path.resolve(__dirname, 'node_modules/@nostr/tools/nip06'),
'nostr-tools/core': path.resolve(__dirname, 'node_modules/nostr-tools/core'),
stream: 'stream-browserify', stream: 'stream-browserify',
util: 'util', util: 'util',
crypto: 'crypto-browserify', crypto: 'crypto-browserify',
@ -32,7 +31,7 @@ export default defineConfig({
mainFields: ['module', 'jsnext:main', 'jsnext', 'main'], mainFields: ['module', 'jsnext:main', 'jsnext', 'main'],
}, },
optimizeDeps: { optimizeDeps: {
include: ['nostr-tools', 'nostr-tools/nip06', 'nostr-tools/core'], include: ['@nostr/tools', '@nostr/tools/nip06', '@jlongster/sql.js'],
esbuildOptions: { esbuildOptions: {
define: { define: {
global: 'globalThis' global: 'globalThis'

9
vite.config.ts

@ -12,10 +12,9 @@ export default defineConfig({
}, },
resolve: { resolve: {
alias: { alias: {
'@': path.resolve(__dirname, './src'), '@': path.resolve(__dirname, 'src'),
'nostr-tools': path.resolve(__dirname, 'node_modules/nostr-tools'), '@nostr/tools': path.resolve(__dirname, 'node_modules/@nostr/tools'),
'nostr-tools/nip06': path.resolve(__dirname, 'node_modules/nostr-tools/nip06'), '@nostr/tools/nip06': path.resolve(__dirname, 'node_modules/@nostr/tools/nip06'),
'nostr-tools/core': path.resolve(__dirname, 'node_modules/nostr-tools/core'),
stream: 'stream-browserify', stream: 'stream-browserify',
util: 'util', util: 'util',
crypto: 'crypto-browserify' crypto: 'crypto-browserify'
@ -23,7 +22,7 @@ export default defineConfig({
mainFields: ['module', 'jsnext:main', 'jsnext', 'main'], mainFields: ['module', 'jsnext:main', 'jsnext', 'main'],
}, },
optimizeDeps: { optimizeDeps: {
include: ['nostr-tools', 'nostr-tools/nip06', 'nostr-tools/core', '@jlongster/sql.js'], include: ['@nostr/tools', '@nostr/tools/nip06', '@jlongster/sql.js'],
esbuildOptions: { esbuildOptions: {
define: { define: {
global: 'globalThis' global: 'globalThis'

Loading…
Cancel
Save