diff --git a/-1750838135249.log b/-1750838135249.log deleted file mode 100644 index 31834a9e..00000000 --- a/-1750838135249.log +++ /dev/null @@ -1,15 +0,0 @@ -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. (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 diff --git a/-1750838461020.log b/-1750838461020.log deleted file mode 100644 index 088eeb4d..00000000 --- a/-1750838461020.log +++ /dev/null @@ -1,4 +0,0 @@ -main.electron.js:1 - - - Failed to load resource: net::ERR_FILE_NOT_FOUND diff --git a/BUILDING.md b/BUILDING.md index 996d6573..9e0106ce 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -9,7 +9,8 @@ For a quick dev environment setup, use [pkgx](https://pkgx.dev). - Node.js (LTS version recommended) - npm (comes with Node.js) - Git -- For desktop builds: Additional build tools based on your OS +- For mobile builds: Android Studio (Android) or Xcode (iOS) +- For desktop builds: Capacitor Electron platform ## Unified Build Scripts @@ -28,8 +29,6 @@ TimeSafari now uses unified build scripts that automatically handle environment | Script | Purpose | Command | |--------|---------|---------| -| `electron-dev.sh` | Electron development | `./scripts/electron-dev.sh` | -| `electron-build.sh` | Electron build | `./scripts/build-electron.sh` | | `capacitor-dev.sh` | Capacitor development | `./scripts/capacitor-dev.sh` | | `capacitor-build.sh` | Capacitor build | `./scripts/build-capacitor.sh` | | `web-dev.sh` | Web development | `./scripts/web-dev.sh` | @@ -41,25 +40,22 @@ All scripts automatically set the correct environment variables for their build | Build Type | VITE_PLATFORM | VITE_PWA_ENABLED | VITE_DISABLE_PWA | NODE_ENV | |------------|---------------|------------------|------------------|----------| -| `electron` | electron | false | true | production* | | `capacitor` | capacitor | false | true | - | | `web` | web | true | false | - | -*NODE_ENV=production only set when production mode is enabled - ### CLI Options All scripts support these options: ```bash # Show help -./scripts/build-electron.sh --help +./scripts/build-capacitor.sh --help # Enable verbose logging -./scripts/build-electron.sh --verbose +./scripts/build-capacitor.sh --verbose # Show environment variables -./scripts/build-electron.sh --env +./scripts/build-capacitor.sh --env ``` ## Forks @@ -102,12 +98,14 @@ npx jsr add @nostr/tools **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"; @@ -210,102 +208,92 @@ VITE_DEFAULT_PUSH_SERVER=https://timesafari.app VITE_PASSKEYS_ENABLED=true ``` -## Desktop Build (Electron) +## Desktop Build (Capacitor Electron) -### Development +### Prerequisites -For development with automatic environment setup: +1. Install Capacitor CLI: -```bash -./scripts/electron-dev.sh -``` + ```bash + npm install -g @capacitor/cli + ``` -### Production Build +2. Add Electron platform: -For production builds with automatic environment setup: + ```bash + npx cap add electron + ``` -```bash -./scripts/build-electron.sh -``` +### Development -### Linux Packaging +For development with automatic environment setup: ```bash -# Build AppImage (recommended) -./scripts/build-electron-linux.sh +# Build web assets +npm run build:capacitor -# Build .deb package -./scripts/build-electron-linux.sh deb +# Sync with Capacitor +npx cap sync electron -# Build production AppImage -./scripts/build-electron-linux.sh prod +# Open in Electron +npx cap open electron ``` -The packaged applications will be in `dist-electron-packages/`: -- AppImage: `dist-electron-packages/TimeSafari-x.x.x.AppImage` -- DEB: `dist-electron-packages/timesafari_x.x.x_amd64.deb` +### Production Build -### macOS Packaging +For production builds: ```bash -# Build standard Mac package -./scripts/build-electron-mac.sh - -# Build universal package (Intel + Apple Silicon) -./scripts/build-electron-mac.sh universal -``` - -The packaged applications will be in `dist-electron-packages/`: -- `.app` bundle: `TimeSafari.app` -- `.dmg` installer: `TimeSafari-x.x.x.dmg` -- `.zip` archive: `TimeSafari-x.x.x-mac.zip` - -### Code Signing and Notarization (macOS) +# Build web assets +npm run build:capacitor -For public distribution on macOS, you need to code sign and notarize your app: +# Sync with Capacitor +npx cap sync electron -1. Set up environment variables in `.env` file: - ```bash - CSC_LINK=/path/to/your/certificate.p12 - CSC_KEY_PASSWORD=your_certificate_password - APPLE_ID=your_apple_id - APPLE_ID_PASSWORD=your_app_specific_password - ``` +# Build Electron app +npx cap build electron +``` -2. Build with signing: - ```bash - ./scripts/build-electron-mac.sh - ``` +### Packaging + +Capacitor Electron uses electron-builder for packaging. Configure the build in `capacitor.config.json`: + +```json +{ + "plugins": { + "ElectronBuilder": { + "buildOptions": { + "appId": "app.timesafari.app", + "productName": "TimeSafari", + "directories": { + "output": "dist-electron-packages" + }, + "files": [ + "dist/**/*", + "electron/**/*" + ], + "linux": { + "target": ["AppImage", "deb"], + "category": "Office" + }, + "mac": { + "target": ["dmg", "zip"], + "category": "public.app-category.productivity" + }, + "win": { + "target": ["nsis", "portable"] + } + } + } + } +} +``` ### Running the Packaged App -- **Linux**: - - AppImage: Make executable and run - ```bash - chmod +x dist-electron-packages/TimeSafari-*.AppImage - ./dist-electron-packages/TimeSafari-*.AppImage - ``` - - DEB: Install and run - ```bash - sudo dpkg -i dist-electron-packages/timesafari_*_amd64.deb - timesafari - ``` - -- **macOS**: - - `.app` bundle: Double-click `TimeSafari.app` in Finder - - `.dmg` installer: - 1. Double-click the `.dmg` file - 2. Drag the app to your Applications folder - 3. Launch from Applications - - `.zip` archive: - 1. Extract the `.zip` file - 2. Move `TimeSafari.app` to your Applications folder - 3. Launch from Applications - - Note: If you get a security warning when running the app: - 1. Right-click the app - 2. Select "Open" - 3. Click "Open" in the security dialog +- **Linux**: AppImage files are self-contained executables +- **macOS**: `.app` bundles can be dragged to Applications folder +- **Windows**: `.exe` installers or portable executables ## Mobile Builds (Capacitor) @@ -601,12 +589,12 @@ For iOS deep links, configure the URL scheme in Xcode: ### Common Issues 1. **Environment Variables Not Set** - - Use `--env` flag to check current environment: `./scripts/build-electron.sh --env` + - Use `--env` flag to check current environment: `./scripts/build-capacitor.sh --env` - Verify `.env` file exists and is properly formatted - Check script output for environment setup messages 2. **Build Failures** - - Use `--verbose` flag for detailed logging: `./scripts/build-electron.sh --verbose` + - Use `--verbose` flag for detailed logging: `./scripts/build-capacitor.sh --verbose` - Check prerequisites are installed - Verify all dependencies are installed: `npm install` @@ -615,14 +603,13 @@ For iOS deep links, configure the URL scheme in Xcode: - Check file permissions on build directories 4. **Platform-Specific Issues** - - **Linux**: Ensure AppImage dependencies are installed - - **macOS**: Check code signing certificates and entitlements - **Android**: Verify Android Studio and SDK are properly configured - **iOS**: Ensure Xcode and certificates are set up correctly + - **Electron**: Check Capacitor Electron platform installation ### Getting Help -- Check script help: `./scripts/build-electron.sh --help` +- Check script help: `./scripts/build-capacitor.sh --help` - Review script documentation in `scripts/README.md` - Test environment setup: `./scripts/test-env.sh` - Test common utilities: `./scripts/test-common.sh` @@ -633,20 +620,47 @@ For iOS deep links, configure the URL scheme in Xcode: |----------|------|-------------|-----------------|-------| | `web` | web | true | false | Standard web browser | | `capacitor` | capacitor | false | true | Mobile app (iOS/Android) | -| `electron` | electron | false | true | Desktop app (Windows/macOS/Linux) | +| `electron` | capacitor | false | true | Desktop app (via Capacitor Electron) | + +## Platform Service Architecture + +TimeSafari uses a unified platform service architecture that works across all platforms: + +### Platform Detection + +The `CapacitorPlatformService` automatically detects the platform and adjusts capabilities: + +```typescript +getCapabilities(): PlatformCapabilities { + const platform = Capacitor.getPlatform(); + const isElectron = platform === "electron"; + + return { + hasFileSystem: true, + hasCamera: true, + isMobile: !isElectron, // false for Electron, true for mobile + isIOS: platform === "ios", + hasFileDownload: isElectron, // Electron can download files directly + needsFileHandlingInstructions: !isElectron, // Mobile needs instructions + isNativeApp: true, + }; +} +``` -## Electron Build: CSS Injection +### Unified Database Layer -The Electron build now uses Vite's built-in CSS handling with a custom plugin (`electron-css-injection`) that automatically injects CSS links into the generated `index.html` file. This replaces the previous manual CSS injection script. +All platforms use the same SQLite database through Capacitor plugins: -**Plugin:** `vite.config.electron.mts` - `electron-css-injection` plugin +- **Mobile**: `@capacitor-community/sqlite` plugin +- **Desktop**: Same plugin via Capacitor Electron +- **Web**: IndexedDB fallback with absurd-sql -**Features:** -- Automatically detects and injects CSS files generated by Vite -- Ensures proper relative paths for Electron builds -- Handles multiple CSS files if present -- Provides detailed logging during build process +### Feature Parity -**No manual intervention required** - CSS injection is handled automatically during the Vite build process. +The same Capacitor plugins work across all platforms: -**Author:** Matthew Raymer +- File system operations +- Camera access +- SQLite database +- Deep linking +- Sharing functionality diff --git a/capacitor.config.json b/capacitor.config.json index 262f9ccd..91b137cb 100644 --- a/capacitor.config.json +++ b/capacitor.config.json @@ -2,7 +2,6 @@ "appId": "app.timesafari", "appName": "TimeSafari", "webDir": "dist", - "bundledWebRuntime": false, "server": { "cleartext": true }, @@ -52,5 +51,47 @@ "*.jsdelivr.net", "api.endorser.ch" ] + }, + "electron": { + "deepLinking": { + "schemes": ["timesafari"] + }, + "buildOptions": { + "appId": "app.timesafari", + "productName": "TimeSafari", + "directories": { + "output": "dist-electron-packages" + }, + "files": [ + "dist/**/*", + "electron/**/*" + ], + "mac": { + "category": "public.app-category.productivity", + "target": [ + { + "target": "dmg", + "arch": ["x64", "arm64"] + } + ] + }, + "win": { + "target": [ + { + "target": "nsis", + "arch": ["x64"] + } + ] + }, + "linux": { + "target": [ + { + "target": "AppImage", + "arch": ["x64"] + } + ], + "category": "Utility" + } + } } } diff --git a/index.html b/index.html index 1b928e13..a69db154 100644 --- a/index.html +++ b/index.html @@ -18,9 +18,6 @@ case 'capacitor': import('./src/main.capacitor.ts'); break; - case 'electron': - import('./src/main.electron.ts'); - break; case 'web': default: import('./src/main.web.ts'); diff --git a/package-lock.json b/package-lock.json index 3ec64b7c..a3ba2fd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7549,24 +7549,33 @@ "license": "MIT" }, "node_modules/@noble/ciphers": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.4.1.tgz", - "integrity": "sha512-QCOA9cgf3Rc33owG0AYBB9wszz+Ul2kramWN8tXG44Gyciud/tbkEqvxRF/IpqQaBpRBNi9f4jdNxqB2CQCIXg==", + "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/@noble/curves": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.2.tgz", - "integrity": "sha512-HxngEd2XUcg9xi20JkwlLCtYwfoFw4JGkuZpT+WlsPD4gB/cxkvTD8fSsoAnphGZhFdZYKeQIPCuFlWPm1uE0g==", + "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.8.0" + "@noble/hashes": "1.3.2" }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "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": "^14.21.3 || >=16" + "node": ">= 16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -7586,12 +7595,12 @@ "optional": true }, "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "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": "^14.21.3 || >=16" + "node": ">= 16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -7650,102 +7659,6 @@ "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": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", @@ -8724,95 +8637,56 @@ ] }, "node_modules/@scure/base": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", - "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } + "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/@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "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.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" + "@noble/curves": "~1.1.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "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.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", - "engines": { - "node": ">= 16" + "@noble/hashes": "1.3.1" }, "funding": { "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32/node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "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.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", - "engines": { - "node": ">= 16" + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip39/node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@simplewebauthn/browser": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-10.0.0.tgz", @@ -9704,9 +9578,9 @@ } }, "node_modules/@types/leaflet": { - "version": "1.9.18", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.18.tgz", - "integrity": "sha512-ht2vsoPjezor5Pmzi5hdsA7F++v5UGq9OlUduWHmMZiuQGIpJ2WS5+Gg9HaAA79gNh1AIPtCqhzejcIZ3lPzXQ==", + "version": "1.9.19", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.19.tgz", + "integrity": "sha512-pB+n2daHcZPF2FDaWa+6B0a0mSDf4dPU35y5iTXsx7x/PzzshiX5atYiS1jlBn43X7XvM8AP+AB26lnSk0J4GA==", "devOptional": true, "license": "MIT", "dependencies": { @@ -10409,6 +10283,15 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@veramo/did-provider-peer/node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@veramo/did-provider-peer/node_modules/@veramo/core-types": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@veramo/core-types/-/core-types-6.0.0.tgz", @@ -11834,7 +11717,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" @@ -12602,9 +12484,9 @@ "license": "MIT" }, "node_modules/browserslist": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", - "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "devOptional": true, "funding": [ { @@ -12622,8 +12504,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001718", - "electron-to-chromium": "^1.5.160", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -12961,7 +12843,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.0", @@ -12993,7 +12874,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -13103,9 +12983,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001723", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", - "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", + "version": "1.0.30001726", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", + "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", "devOptional": true, "funding": [ { @@ -14860,7 +14740,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -15091,6 +14970,24 @@ "node": ">=18" } }, + "node_modules/did-jwt/node_modules/@noble/ciphers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.4.1.tgz", + "integrity": "sha512-QCOA9cgf3Rc33owG0AYBB9wszz+Ul2kramWN8tXG44Gyciud/tbkEqvxRF/IpqQaBpRBNi9f4jdNxqB2CQCIXg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/did-jwt/node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/did-jwt/node_modules/multiformats": { "version": "9.9.0", "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", @@ -15582,9 +15479,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.170", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.170.tgz", - "integrity": "sha512-GP+M7aeluQo9uAyiTCxgIj/j+PrWhMlY7LFVj8prlsPljd0Fdg9AprlfUi+OCSFWy9Y5/2D/Jrj9HS8Z4rpKWA==", + "version": "1.5.173", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.173.tgz", + "integrity": "sha512-2bFhXP2zqSfQHugjqJIDFVwa+qIxyNApenmXTp9EjaKtdPrES5Qcn9/aSFy/NaP2E+fWG/zxKu/LBvY36p5VNQ==", "devOptional": true, "license": "ISC" }, @@ -16016,9 +15913,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.0.tgz", - "integrity": "sha512-8qsOYwkkGrahrgoUv76NZi23koqXOGiiEzXMrT8Q7VcYaUISR+5MorIUxfWqYXN0fN/31WbSrxCxFkVQ43wwrA==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.1.tgz", + "integrity": "sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==", "dev": true, "license": "MIT", "dependencies": { @@ -16238,6 +16135,18 @@ "@noble/hashes": "^1.4.0" } }, + "node_modules/ethereum-bloom-filters/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ethereum-cryptography": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", @@ -16274,6 +16183,42 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/ethereum-cryptography/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethereum-cryptography/node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethereum-cryptography/node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ethereumjs-util": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", @@ -16341,18 +16286,6 @@ "node": ">=14.0.0" } }, - "node_modules/ethers/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/ethers/node_modules/@noble/hashes": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", @@ -16446,6 +16379,15 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/ethr-did/node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ethr-did/node_modules/did-jwt": { "version": "8.0.17", "resolved": "https://registry.npmjs.org/did-jwt/-/did-jwt-8.0.17.tgz", @@ -17222,7 +17164,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dev": true, "license": "MIT", "dependencies": { "is-callable": "^1.2.7" @@ -18102,7 +18043,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -18705,7 +18645,6 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -19149,7 +19088,6 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dev": true, "license": "MIT", "dependencies": { "which-typed-array": "^1.1.16" @@ -19236,7 +19174,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, "license": "MIT" }, "node_modules/isbinaryfile": { @@ -23979,21 +23916,53 @@ } }, "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", + "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", "license": "MIT", "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "create-hash": "~1.1.3", + "create-hmac": "^1.1.7", + "ripemd160": "=2.0.1", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.11", + "to-buffer": "^1.2.0" }, "engines": { "node": ">=0.12" } }, + "node_modules/pbkdf2/node_modules/create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "sha.js": "^2.4.0" + } + }, + "node_modules/pbkdf2/node_modules/hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1" + } + }, + "node_modules/pbkdf2/node_modules/ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", + "license": "MIT", + "dependencies": { + "hash-base": "^2.0.0", + "inherits": "^2.0.1" + } + }, "node_modules/pe-library": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz", @@ -24163,7 +24132,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -24373,9 +24341,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.1.tgz", + "integrity": "sha512-5xGWRa90Sp2+x1dQtNpIpeOQpTDBs9cZDmA/qs2vDNN2i18PdapqY7CmBeyLlMuGqXJRIOPaCaVZTLNQRWUH/A==", "dev": true, "license": "MIT", "bin": { @@ -24535,9 +24503,9 @@ } }, "node_modules/protons-runtime": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/protons-runtime/-/protons-runtime-5.5.0.tgz", - "integrity": "sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/protons-runtime/-/protons-runtime-5.6.0.tgz", + "integrity": "sha512-/Kde+sB9DsMFrddJT/UZWe6XqvL7SL5dbag/DBCElFKhkwDj7XKt53S+mzLyaDP5OqS0wXjV5SA572uWDaT0Hg==", "license": "Apache-2.0 OR MIT", "dependencies": { "uint8-varint": "^2.0.2", @@ -24744,9 +24712,9 @@ } }, "node_modules/qrcode-generator": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.5.0.tgz", - "integrity": "sha512-sqo7otiDq5rA4djRkFI7IjLQqxRrLpIou0d3rqr03JJLUGf5raPh91xCio+lFFbQf0SlcVckStz0EmDEX3EeZA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.5.1.tgz", + "integrity": "sha512-u0zerMlMtKBgkDlDzWXG/7F7jo2En1d7bivC7V33HGqP62XxGiHGnbCJNkSCMxGfNlhXGBGEIamNMHbZ4P4mLg==", "license": "MIT" }, "node_modules/qrcode-terminal": { @@ -26906,7 +26874,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -28836,6 +28803,20 @@ "optional": true, "peer": true }, + "node_modules/to-buffer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", + "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -29080,7 +29061,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.3", @@ -29169,9 +29149,9 @@ "license": "MIT" }, "node_modules/typeorm": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.24.tgz", - "integrity": "sha512-4IrHG7A0tY8l5gEGXfW56VOMfUVWEkWlH/h5wmcyZ+V8oCiLj7iTPp0lEjMEZVrxEkGSdP9ErgTKHKXQApl/oA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.25.tgz", + "integrity": "sha512-fTKDFzWXKwAaBdEMU4k661seZewbNYET4r1J/z3Jwf+eAvlzMVpTLKAVcAzg75WwQk7GDmtsmkZ5MfkmXCiFWg==", "license": "MIT", "dependencies": { "@sqltools/formatter": "^1.2.5", @@ -30352,7 +30332,6 @@ "version": "1.1.19", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", - "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", diff --git a/package.json b/package.json index 8da807d5..4f75e03e 100644 --- a/package.json +++ b/package.json @@ -20,25 +20,14 @@ "test:ios": "node scripts/test-ios.js", "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)", - "clean:electron": "rimraf dist-electron", - "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_GIT_HASH=`git log -1 --pretty=format:%h` 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", - "electron:dev": "./scripts/electron-dev.sh", - "electron:start": "electron .", "clean:android": "adb uninstall app.timesafari.app || true", "build:android": "./scripts/build-android.sh", - "electron:build-linux": "./scripts/build-electron-linux.sh", - "electron:build-linux-deb": "./scripts/build-electron-linux.sh deb", - "electron:build-linux-prod": "./scripts/build-electron-linux.sh prod", - "build:electron-prod": "NODE_ENV=production npm run build:electron", "fastlane:ios:beta": "cd ios && fastlane beta", "fastlane:ios:release": "cd ios && fastlane release", "fastlane:android:beta": "cd android && fastlane beta", - "fastlane:android:release": "cd android && fastlane release", - "electron:build-mac": "./scripts/build-electron-mac.sh", - "electron:build-mac-universal": "./scripts/build-electron-mac.sh universal" + "fastlane:android:release": "cd android && fastlane release" }, "dependencies": { "@capacitor-community/sqlite": "6.0.2", @@ -145,8 +134,6 @@ "browserify-fs": "^1.0.0", "concurrently": "^8.2.2", "crypto-browserify": "^3.12.1", - "electron": "^33.2.1", - "electron-builder": "^25.1.8", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", @@ -163,58 +150,5 @@ "typescript": "~5.2.2", "vite": "^5.2.0", "vite-plugin-pwa": "^1.0.0" - }, - "main": "./dist-electron/main.js", - "build": { - "appId": "app.timesafari.app", - "productName": "TimeSafari", - "directories": { - "output": "dist-electron-packages" - }, - "files": [ - "dist-electron/**/*", - "dist/**/*" - ], - "extraResources": [ - { - "from": "dist-electron/www", - "to": "www" - } - ], - "linux": { - "target": [ - "AppImage", - "deb" - ], - "category": "Office", - "icon": "build/icon.png" - }, - "asar": true, - "mac": { - "target": [ - "dmg", - "zip" - ], - "category": "public.app-category.productivity", - "icon": "build/icon.png", - "hardenedRuntime": true, - "gatekeeperAssess": false, - "entitlements": "ios/App/App/entitlements.mac.plist", - "entitlementsInherit": "ios/App/App/entitlements.mac.plist" - }, - "dmg": { - "contents": [ - { - "x": 130, - "y": 220 - }, - { - "x": 410, - "y": 220, - "type": "link", - "path": "/Applications" - } - ] - } } } diff --git a/scripts/README.md b/scripts/README.md index e67d21e1..71f61de4 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -27,7 +27,6 @@ All scripts automatically handle environment variables for different build types |----------|------|-------------|-----------------|--------------| | `web` | web | true | false | `build-web.sh` | | `capacitor` | capacitor | false | true | `build-capacitor.sh` | -| `electron` | electron | false | true | `build-electron.sh` | #### Automatic Environment Setup @@ -96,10 +95,7 @@ exit 0 ### Build Scripts -- **`build-electron.sh`**: Complete Electron build process - **`build-android.sh`**: Complete Android build process -- **`build-electron-linux.sh`**: Linux Electron packaging (AppImage, .deb) -- **`build-electron-mac.sh`**: macOS Electron packaging (standard, universal) ### Development Scripts @@ -152,10 +148,8 @@ print_footer "Script Title" ``` ### Building Applications -```bash -# Build Electron -./scripts/build-electron.sh +```bash # Build Android ./scripts/build-android.sh @@ -170,19 +164,21 @@ print_footer "Script Title" ``` ### Development Workflows + ```bash -# Start Electron development -./scripts/electron-dev.sh +# Start development +npm run dev ``` ## Environment Variable Features ### Automatic Setup + All scripts automatically configure the correct environment variables for their build type: ```bash -# Electron builds automatically get: -export VITE_PLATFORM=electron +# Capacitor builds automatically get: +export VITE_PLATFORM=capacitor export VITE_PWA_ENABLED=false export VITE_DISABLE_PWA=true export DEBUG_MIGRATIONS=0 @@ -214,7 +210,6 @@ validate_env_vars "VITE_API_URL" "VITE_DEBUG" || exit 1 View current environment variables with the `--env` flag: ```bash -./scripts/build-electron.sh --env ./scripts/test-env.sh --env ``` diff --git a/scripts/build-electron-linux.sh b/scripts/build-electron-linux.sh deleted file mode 100755 index 7d7cbccf..00000000 --- a/scripts/build-electron-linux.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash -# build-electron-linux.sh -# Author: Matthew Raymer -# Description: Electron Linux build script for TimeSafari application -# This script builds Electron packages for Linux with support for different formats. -# -# Usage: ./scripts/build-electron-linux.sh [deb|prod] -# - No argument: Builds AppImage -# - deb: Builds .deb package -# - prod: Builds production AppImage -# -# Exit Codes: -# 1 - Build failed -# 2 - Invalid argument - -# Exit on any error -set -e - -# Source common utilities -source "$(dirname "$0")/common.sh" - -# Parse command line arguments -parse_args "$@" - -# Parse build type argument -BUILD_TYPE=${1:-"appimage"} -PRODUCTION=false - -case $BUILD_TYPE in - "deb") - BUILD_TARGET="deb" - log_info "Building .deb package" - ;; - "prod") - BUILD_TARGET="AppImage" - PRODUCTION=true - log_info "Building production AppImage" - ;; - "appimage"|"") - BUILD_TARGET="AppImage" - log_info "Building AppImage" - ;; - *) - log_error "Invalid build type: $BUILD_TYPE" - log_error "Usage: $0 [deb|prod]" - exit 2 - ;; -esac - -# Print build header -print_header "TimeSafari Electron Linux Build" -log_info "Starting Linux build process at $(date)" -log_info "Build type: $BUILD_TYPE" -log_info "Build target: $BUILD_TARGET" -log_info "Production mode: $PRODUCTION" - -# Setup environment for Electron build -setup_build_env "electron" "$PRODUCTION" - -# Setup application directories -setup_app_directories - -# Load environment from .env file if it exists -load_env_file ".env" - -# Step 1: Build Electron application -if [ "$PRODUCTION" = true ]; then - safe_execute "Building production Electron application" "npm run build:electron-prod" || exit 1 -else - safe_execute "Building Electron application" "npm run build:electron" || exit 1 -fi - -# Step 2: Build package -safe_execute "Building Linux package" "npx electron-builder --linux $BUILD_TARGET" || exit 1 - -# Print build summary -log_success "Linux build completed successfully!" -log_info "Package type: $BUILD_TARGET" -print_footer "Linux Build" - -# Exit with success -exit 0 \ No newline at end of file diff --git a/scripts/build-electron-mac.sh b/scripts/build-electron-mac.sh deleted file mode 100644 index 5504ca6d..00000000 --- a/scripts/build-electron-mac.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash -# build-electron-mac.sh -# Author: Matthew Raymer -# Description: Electron Mac build script for TimeSafari application -# This script builds Electron packages for macOS with support for universal builds. -# -# Usage: ./scripts/build-electron-mac.sh [universal] -# - No argument: Builds standard Mac package -# - universal: Builds universal Mac package (Intel + Apple Silicon) -# -# Exit Codes: -# 1 - Build failed -# 2 - Invalid argument - -# Exit on any error -set -e - -# Source common utilities -source "$(dirname "$0")/common.sh" - -# Parse command line arguments -parse_args "$@" - -# Parse build type argument -BUILD_TYPE=${1:-"standard"} -UNIVERSAL=false - -case $BUILD_TYPE in - "universal") - UNIVERSAL=true - log_info "Building universal Mac package (Intel + Apple Silicon)" - ;; - "standard"|"") - log_info "Building standard Mac package" - ;; - *) - log_error "Invalid build type: $BUILD_TYPE" - log_error "Usage: $0 [universal]" - exit 2 - ;; -esac - -# Print build header -print_header "TimeSafari Electron Mac Build" -log_info "Starting Mac build process at $(date)" -log_info "Build type: $BUILD_TYPE" -log_info "Universal build: $UNIVERSAL" - -# Setup environment for Electron build (production mode for packaging) -setup_build_env "electron" "true" - -# Setup application directories -setup_app_directories - -# Load environment from .env file if it exists -load_env_file ".env" - -# Step 1: Build Electron application -safe_execute "Building Electron application" "npm run build:electron-prod" || exit 1 - -# Step 2: Build package -if [ "$UNIVERSAL" = true ]; then - safe_execute "Building universal Mac package" "npx electron-builder --mac --universal" || exit 1 -else - safe_execute "Building Mac package" "npx electron-builder --mac" || exit 1 -fi - -# Print build summary -log_success "Mac build completed successfully!" -log_info "Package type: $([ "$UNIVERSAL" = true ] && echo "Universal" || echo "Standard")" -print_footer "Mac Build" - -# Exit with success -exit 0 \ No newline at end of file diff --git a/scripts/build-electron.js b/scripts/build-electron.js deleted file mode 100644 index 74f172ea..00000000 --- a/scripts/build-electron.js +++ /dev/null @@ -1,148 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -console.log('Starting electron build process...'); - -// Define paths -const electronDistPath = path.join(__dirname, '..', 'dist-electron'); -const wwwPath = path.join(electronDistPath, 'www'); - -// Create www directory if it doesn't exist -if (!fs.existsSync(wwwPath)) { - fs.mkdirSync(wwwPath, { recursive: true }); -} - -// Copy the Vite-built index.html to www directory -const viteIndexPath = path.join(electronDistPath, 'index.html'); -const wwwIndexPath = path.join(wwwPath, 'index.html'); - -if (fs.existsSync(viteIndexPath)) { - console.log('Copying Vite-built index.html to www directory...'); - fs.copyFileSync(viteIndexPath, wwwIndexPath); - - // Remove the original index.html from dist-electron root - fs.unlinkSync(viteIndexPath); - console.log('Moved index.html to www directory'); -} else { - console.error('Vite-built index.html not found at:', viteIndexPath); - process.exit(1); -} - -// Copy assets directory if it exists in dist-electron -const assetsSrc = path.join(electronDistPath, 'assets'); -const assetsDest = path.join(wwwPath, 'assets'); - -if (fs.existsSync(assetsSrc)) { - console.log('Moving assets directory to www...'); - if (fs.existsSync(assetsDest)) { - fs.rmSync(assetsDest, { recursive: true, force: true }); - } - fs.renameSync(assetsSrc, assetsDest); - console.log('Moved assets directory to www'); -} - -// Copy favicon if it exists -const faviconSrc = path.join(electronDistPath, 'favicon.ico'); -const faviconDest = path.join(wwwPath, 'favicon.ico'); - -if (fs.existsSync(faviconSrc)) { - console.log('Moving favicon to www...'); - fs.renameSync(faviconSrc, faviconDest); - console.log('Moved favicon to www'); -} - -// Remove service worker files from www directory -const swFilesToRemove = [ - 'sw.js', - 'sw.js.map', - 'workbox-*.js', - 'workbox-*.js.map', - 'registerSW.js', - 'manifest.webmanifest' -]; - -console.log('Removing service worker files...'); -swFilesToRemove.forEach(pattern => { - const files = fs.readdirSync(wwwPath).filter(file => - file.match(new RegExp(pattern.replace(/\*/g, '.*'))) - ); - files.forEach(file => { - const filePath = path.join(wwwPath, file); - console.log(`Removing ${filePath}`); - try { - fs.unlinkSync(filePath); - } catch (err) { - console.warn(`Could not remove ${filePath}:`, err.message); - } - }); -}); - -// Also check and remove from assets directory -if (fs.existsSync(assetsDest)) { - swFilesToRemove.forEach(pattern => { - const files = fs.readdirSync(assetsDest).filter(file => - file.match(new RegExp(pattern.replace(/\*/g, '.*'))) - ); - files.forEach(file => { - const filePath = path.join(assetsDest, file); - console.log(`Removing ${filePath}`); - try { - fs.unlinkSync(filePath); - } catch (err) { - console.warn(`Could not remove ${filePath}:`, err.message); - } - }); - }); -} - -// Verify the final index.html structure -const finalIndexContent = fs.readFileSync(wwwIndexPath, 'utf8'); -console.log('Final index.html structure:'); -console.log('- Has CSS link:', finalIndexContent.includes(' { - if (file !== 'main.js' && file !== 'preload.js' && file !== 'www') { - const filePath = path.join(electronDistPath, file); - console.log(`Removing remaining file: ${file}`); - try { - if (fs.statSync(filePath).isDirectory()) { - fs.rmSync(filePath, { recursive: true, force: true }); - } else { - fs.unlinkSync(filePath); - } - } catch (err) { - console.warn(`Could not remove ${filePath}:`, err.message); - } - } -}); - -console.log('Electron build process completed successfully'); -console.log('Final structure:'); -console.log('- Main process:', path.join(electronDistPath, 'main.js')); -console.log('- Preload script:', path.join(electronDistPath, 'preload.js')); -console.log('- Web assets:', path.join(electronDistPath, 'www')); \ No newline at end of file diff --git a/scripts/build-electron.sh b/scripts/build-electron.sh deleted file mode 100755 index 5aa36ac4..00000000 --- a/scripts/build-electron.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -# build-electron.sh -# Author: Matthew Raymer -# Description: Electron build script for TimeSafari application -# This script handles the complete Electron build process including cleanup, -# TypeScript compilation, Vite build, and Electron-specific setup. -# -# Exit Codes: -# 1 - Cleanup failed -# 2 - TypeScript compilation failed -# 3 - Vite build failed -# 4 - Electron build script failed - -# Exit on any error -set -e - -# Source common utilities -source "$(dirname "$0")/common.sh" - -# Parse command line arguments -parse_args "$@" - -# Print build header -print_header "TimeSafari Electron Build Process" -log_info "Starting Electron build process at $(date)" - -# Setup environment for Electron build -setup_build_env "electron" - -# Setup application directories -setup_app_directories - -# Load environment from .env file if it exists -load_env_file ".env" - -# Step 1: Clean previous builds -safe_execute "Cleaning previous builds" "npm run clean:electron" || exit 1 - -# Step 2: Compile TypeScript for Electron -safe_execute "Compiling TypeScript for Electron" "npx tsc -p tsconfig.electron.json" || exit 2 - -# Step 3: Build with Vite -safe_execute "Building with Vite" "npx vite build --config vite.config.electron.mts" || exit 3 - -# Step 4: Run Electron build script -safe_execute "Running Electron build script" "node scripts/build-electron.js" || exit 4 - -# Print build summary -log_success "Electron build completed successfully!" -print_footer "Electron Build" - -# Exit with success -exit 0 \ No newline at end of file diff --git a/scripts/common.sh b/scripts/common.sh index ab9e6c7a..1cc699f9 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -176,16 +176,6 @@ setup_build_env() { log_debug "Set VITE_GIT_HASH=$git_hash" case $build_type in - "electron") - export VITE_PLATFORM=electron - export VITE_PWA_ENABLED=false - export VITE_DISABLE_PWA=true - export DEBUG_MIGRATIONS=0 - if [ "$production" = true ]; then - export NODE_ENV=production - log_debug "Set production mode for Electron" - fi - ;; "capacitor") export VITE_PLATFORM=capacitor export VITE_PWA_ENABLED=false @@ -227,7 +217,6 @@ setup_app_directories() { # Create build directories if they don't exist mkdir -p dist - mkdir -p dist-electron log_debug "Application directories created" } diff --git a/scripts/electron-dev.sh b/scripts/electron-dev.sh deleted file mode 100755 index 2bd76e02..00000000 --- a/scripts/electron-dev.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash -# electron-dev.sh -# Author: Matthew Raymer -# Description: Electron development script for TimeSafari application -# This script builds the application and starts Electron for development. -# -# Exit Codes: -# 1 - Build failed -# 2 - Electron start failed - -# Exit on any error -set -e - -# Source common utilities -source "$(dirname "$0")/common.sh" - -# Parse command line arguments -parse_args "$@" - -# Print dev header -print_header "TimeSafari Electron Development" -log_info "Starting Electron development at $(date)" - -# Setup environment for Electron development -setup_build_env "electron" - -# Setup application directories -setup_app_directories - -# Load environment from .env file if it exists -load_env_file ".env" - -# Step 1: Build the application -safe_execute "Building application" "npm run build" || exit 1 - -# Step 2: Start Electron -safe_execute "Starting Electron" "electron ." || exit 2 - -# Print dev summary -log_success "Electron development session ended" -print_footer "Electron Development" - -# Exit with success -exit 0 \ No newline at end of file diff --git a/scripts/test-env.sh b/scripts/test-env.sh index 5220d871..2baad4e6 100755 --- a/scripts/test-env.sh +++ b/scripts/test-env.sh @@ -17,37 +17,34 @@ parse_args "$@" print_header "Environment Variable Test" log_info "Testing environment variable handling at $(date)" -# Test 1: Electron environment -log_info "Test 1: Setting up Electron environment..." -setup_build_env "electron" -print_env_vars "VITE_" - -# Test 2: Capacitor environment -log_info "Test 2: Setting up Capacitor environment..." +# Test 1: Capacitor environment +log_info "Test 1: Setting up Capacitor environment..." setup_build_env "capacitor" print_env_vars "VITE_" +echo "" -# Test 3: Web environment -log_info "Test 3: Setting up Web environment..." +# Test 2: Web environment +log_info "Test 2: Setting up Web environment..." setup_build_env "web" print_env_vars "VITE_" +echo "" -# Test 4: Production Electron environment -log_info "Test 4: Setting up Production Electron environment..." -setup_build_env "electron" "true" +# Test 3: Production Capacitor environment +log_info "Test 3: Setting up Production Capacitor environment..." +setup_build_env "capacitor" "true" print_env_vars "VITE_" -print_env_vars "NODE_ENV" +echo "" -# Test 5: Application directories -log_info "Test 5: Setting up application directories..." +# Test 4: Application directories +log_info "Test 4: Setting up application directories..." setup_app_directories -# Test 6: Load .env file (if it exists) -log_info "Test 6: Loading .env file..." +# Test 5: Load .env file (if it exists) +log_info "Test 5: Loading .env file..." load_env_file ".env" -# Test 7: Git hash -log_info "Test 7: Getting git hash..." +# Test 6: Git hash +log_info "Test 6: Getting git hash..." GIT_HASH=$(get_git_hash) log_info "Git hash: $GIT_HASH" diff --git a/src/electron/main.js b/src/electron/main.js deleted file mode 100644 index 978e105d..00000000 --- a/src/electron/main.js +++ /dev/null @@ -1,174 +0,0 @@ -const { app, BrowserWindow } = require("electron"); -const path = require("path"); -const fs = require("fs"); -const logger = require("../utils/logger"); - -// 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 - "", // 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 - 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;" + - "img-src 'self' data: https: blob:;" + - "script-src 'self' 'unsafe-inline' 'unsafe-eval';" + - "style-src 'self' 'unsafe-inline';" + - "font-src 'self' data:;", - ], - }, - }); - }, - ); - - // 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(); - } -} - -// 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); -}); diff --git a/src/electron/main.ts b/src/electron/main.ts deleted file mode 100644 index 89e348f0..00000000 --- a/src/electron/main.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { app, BrowserWindow } from "electron"; -import path from "path"; -import fs from "fs"; - -// Simple logger implementation -const logger = { - // eslint-disable-next-line no-console - log: (...args: unknown[]) => console.log(...args), - // eslint-disable-next-line no-console - error: (...args: unknown[]) => console.error(...args), - // eslint-disable-next-line no-console - info: (...args: unknown[]) => console.info(...args), - // eslint-disable-next-line no-console - warn: (...args: unknown[]) => console.warn(...args), - // eslint-disable-next-line no-console - debug: (...args: unknown[]) => console.debug(...args), -}; - -// Check if running in dev mode -const isDev = process.argv.includes("--inspect"); - -async function createWindow(): Promise { - // Add before createWindow function - 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("Preload exists:", fs.existsSync(preloadPath)); - - // Log environment and paths - logger.log("process.cwd():", process.cwd()); - logger.log("__dirname:", __dirname); - logger.log("app.getAppPath():", app.getAppPath()); - logger.log("app.isPackaged:", app.isPackaged); - - // List files in __dirname and __dirname/www - try { - logger.log("Files in __dirname:", fs.readdirSync(__dirname)); - const wwwDir = path.join(__dirname, "www"); - if (fs.existsSync(wwwDir)) { - logger.log("Files in www:", fs.readdirSync(wwwDir)); - } else { - logger.log("www directory does not exist in __dirname"); - } - } catch (e) { - logger.error("Error reading directories:", e); - } - - // Create the browser window. - const mainWindow = new BrowserWindow({ - width: 1200, - height: 800, - webPreferences: { - nodeIntegration: false, - contextIsolation: true, - webSecurity: true, - allowRunningInsecureContent: false, - preload: preloadPath, - }, - }); - - // Always open DevTools for now - mainWindow.webContents.openDevTools(); - - // Intercept requests to robustly fix asset paths for Electron - mainWindow.webContents.session.webRequest.onBeforeRequest( - { urls: ["*://*/*"] }, - (details, callback) => { - const url = details.url; - logger.log('[main.ts] Intercepted request:', url); - - // Match both file:///assets/... and /assets/... - const assetMatch = url.match(/(?:file:\/\/\/|file:\/\/|https?:\/\/[^\/]+)?\/assets\/(.+)/); - if (assetMatch) { - const assetRelPath = assetMatch[1]; - const assetAbsPath = path.join(app.getAppPath(), "dist-electron", "www", "assets", assetRelPath); - logger.log('[main.ts] Asset request detected:', { - originalUrl: url, - assetRelPath, - assetAbsPath, - exists: fs.existsSync(assetAbsPath) - }); - - if (fs.existsSync(assetAbsPath)) { - const newUrl = `file://${assetAbsPath}`; - logger.log('[main.ts] Redirecting to:', newUrl); - callback({ redirectURL: newUrl }); - return; - } else { - logger.error('[main.ts] Asset file not found:', assetAbsPath); - } - } - callback({}); - } - ); - - 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()); - } - - let indexPath: string; - if (app.isPackaged) { - indexPath = path.join( - app.getAppPath(), - "dist-electron", - "www", - "index.html", - ); - logger.log("[main.ts] Using packaged indexPath:", indexPath); - } else { - indexPath = path.resolve( - process.cwd(), - "dist-electron", - "www", - "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) { - logger.log("Loading index from:", indexPath); - logger.log("www path:", path.join(__dirname, "www")); - logger.log("www assets path:", path.join(__dirname, "www", "assets")); - } - - // Add CSP headers to allow API connections - 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;" + - "img-src 'self' data: https: blob:;" + - "script-src 'self' 'unsafe-inline' 'unsafe-eval';" + - "style-src 'self' 'unsafe-inline';" + - "font-src 'self' data:;", - ], - }, - }); - }, - ); - - // Load the index.html with the correct base URL for assets - const baseURL = `file://${path.dirname(indexPath)}/`; - logger.log('[main.ts] Loading with base URL:', baseURL); - - try { - await mainWindow.loadURL(`file://${indexPath}`); - 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(); - } -} - -// 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); -}); diff --git a/src/electron/preload.js b/src/electron/preload.js deleted file mode 100644 index 2b37f099..00000000 --- a/src/electron/preload.js +++ /dev/null @@ -1,91 +0,0 @@ -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(`[Preload] ${message}`, ...args); - /* eslint-enable no-console */ - } - }, - warn: (message, ...args) => { - // 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(`[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 -const getPath = (pathType) => { - switch (pathType) { - case "userData": - return ( - process.env.APPDATA || - (process.platform === "darwin" - ? `${process.env.HOME}/Library/Application Support` - : `${process.env.HOME}/.local/share`) - ); - case "home": - return process.env.HOME; - case "appPath": - return process.resourcesPath; - default: - return ""; - } -}; - -logger.info("Preload script starting..."); - -// Force electron platform in the renderer process -window.process = { env: { VITE_PLATFORM: "electron" } }; - -try { - contextBridge.exposeInMainWorld("electronAPI", { - // Path utilities - getPath, - - // IPC functions - send: (channel, data) => { - const validChannels = ["toMain"]; - if (validChannels.includes(channel)) { - ipcRenderer.send(channel, data); - } - }, - receive: (channel, func) => { - const validChannels = ["fromMain"]; - if (validChannels.includes(channel)) { - ipcRenderer.on(channel, (event, ...args) => func(...args)); - } - }, - // Environment info - env: { - isElectron: true, - isDev: process.env.NODE_ENV === "development", - platform: "electron", // Explicitly set platform - }, - // Path utilities - getBasePath: () => { - return process.env.NODE_ENV === "development" ? "/" : "./"; - }, - }); - - logger.info("Preload script completed successfully"); -} catch (error) { - logger.error("Error in preload script:", error); -} diff --git a/src/main.electron.ts b/src/main.electron.ts deleted file mode 100644 index 0a20d8f8..00000000 --- a/src/main.electron.ts +++ /dev/null @@ -1,17 +0,0 @@ -import './assets/styles/tailwind.css'; -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"); diff --git a/src/main.web.ts b/src/main.web.ts index ff149056..5909655f 100644 --- a/src/main.web.ts +++ b/src/main.web.ts @@ -6,7 +6,7 @@ const platform = process.env.VITE_PLATFORM; const pwa_enabled = process.env.VITE_PWA_ENABLED === "true"; // Only import service worker for web builds -if (platform !== "electron" && pwa_enabled) { +if (pwa_enabled) { import("./registerServiceWorker"); // Web PWA support } diff --git a/src/registerServiceWorker.ts b/src/registerServiceWorker.ts index e1f328b8..139f44e9 100644 --- a/src/registerServiceWorker.ts +++ b/src/registerServiceWorker.ts @@ -2,18 +2,10 @@ import { register } from "register-service-worker"; -// Check if we're in an Electron environment -const isElectron = - process.env.VITE_PLATFORM === "electron" || - process.env.VITE_DISABLE_PWA === "true" || - window.navigator.userAgent.toLowerCase().includes("electron"); - // Only register service worker if: -// 1. Not in Electron -// 2. PWA is explicitly enabled -// 3. In production mode +// 1. PWA is explicitly enabled +// 2. In production mode if ( - !isElectron && process.env.VITE_PWA_ENABLED === "true" && process.env.NODE_ENV === "production" ) { @@ -45,11 +37,9 @@ if ( } else { console.log( `Service worker registration skipped - ${ - isElectron - ? "running in Electron" - : process.env.VITE_PWA_ENABLED !== "true" - ? "PWA not enabled" - : "not in production mode" + process.env.VITE_PWA_ENABLED !== "true" + ? "PWA not enabled" + : "not in production mode" }`, ); } diff --git a/src/router/index.ts b/src/router/index.ts index fabce1b5..ac78bfc7 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -277,14 +277,9 @@ const routes: Array = [ }, ]; -const isElectron = window.location.protocol === "file:"; -const initialPath = isElectron - ? window.location.pathname.split("/dist-electron/www/")[1] || "/" - : window.location.pathname; +const initialPath = window.location.pathname; -const history = isElectron - ? createMemoryHistory() // Memory history for Electron - : createWebHistory("/"); // Add base path for web apps +const history = createWebHistory("/"); // Add base path for web apps /** @type {*} */ const router = createRouter({ diff --git a/src/services/PlatformServiceFactory.ts b/src/services/PlatformServiceFactory.ts index 12af421c..a0fb9204 100644 --- a/src/services/PlatformServiceFactory.ts +++ b/src/services/PlatformServiceFactory.ts @@ -1,7 +1,6 @@ import { PlatformService } from "./PlatformService"; import { WebPlatformService } from "./platforms/WebPlatformService"; import { CapacitorPlatformService } from "./platforms/CapacitorPlatformService"; -import { ElectronPlatformService } from "./platforms/ElectronPlatformService"; /** * Factory class for creating platform-specific service implementations. @@ -10,7 +9,6 @@ import { ElectronPlatformService } from "./platforms/ElectronPlatformService"; * The factory determines which platform implementation to use based on the VITE_PLATFORM * environment variable. Supported platforms are: * - capacitor: Mobile platform using Capacitor - * - electron: Desktop platform using Electron * - web: Default web platform (fallback) * * @example @@ -39,9 +37,6 @@ export class PlatformServiceFactory { case "capacitor": PlatformServiceFactory.instance = new CapacitorPlatformService(); break; - case "electron": - PlatformServiceFactory.instance = new ElectronPlatformService(); - break; case "web": default: PlatformServiceFactory.instance = new WebPlatformService(); diff --git a/src/services/platforms/CapacitorPlatformService.ts b/src/services/platforms/CapacitorPlatformService.ts index 704a740d..aaa4dc07 100644 --- a/src/services/platforms/CapacitorPlatformService.ts +++ b/src/services/platforms/CapacitorPlatformService.ts @@ -244,13 +244,15 @@ export class CapacitorPlatformService implements PlatformService { * @returns Platform capabilities object */ getCapabilities(): PlatformCapabilities { + const platform = Capacitor.getPlatform(); + return { hasFileSystem: true, hasCamera: true, - isMobile: true, - isIOS: Capacitor.getPlatform() === "ios", - hasFileDownload: false, - needsFileHandlingInstructions: true, + isMobile: true, // Capacitor is always mobile + isIOS: platform === "ios", + hasFileDownload: false, // Mobile platforms need sharing + needsFileHandlingInstructions: true, // Mobile needs instructions isNativeApp: true, }; } diff --git a/src/services/platforms/ElectronPlatformService.ts b/src/services/platforms/ElectronPlatformService.ts deleted file mode 100644 index 9ba7ca60..00000000 --- a/src/services/platforms/ElectronPlatformService.ts +++ /dev/null @@ -1,358 +0,0 @@ -import { - ImageResult, - PlatformService, - PlatformCapabilities, -} from "../PlatformService"; -import { logger } from "../../utils/logger"; -import { QueryExecResult, SqlValue } from "@/interfaces/database"; -import { - SQLiteConnection, - SQLiteDBConnection, - CapacitorSQLite, - Changes, -} from "@capacitor-community/sqlite"; -import { DEFAULT_ENDORSER_API_SERVER } from "@/constants/app"; - -interface Migration { - name: string; - sql: string; -} - -/** - * Platform service implementation for Electron (desktop) platform. - * Provides native desktop functionality through Electron and Capacitor plugins for: - * - File system operations (TODO) - * - Camera integration (TODO) - * - SQLite database operations - * - System-level features (TODO) - */ -export class ElectronPlatformService implements PlatformService { - private sqlite: SQLiteConnection; - private db: SQLiteDBConnection | null = null; - private dbName = "timesafari.db"; - private initialized = false; - - constructor() { - this.sqlite = new SQLiteConnection(CapacitorSQLite); - } - - private async initializeDatabase(): Promise { - if (this.initialized) { - return; - } - - try { - // Create/Open database - this.db = await this.sqlite.createConnection( - this.dbName, - false, - "no-encryption", - 1, - false, - ); - - await this.db.open(); - - // Set journal mode to WAL for better performance - await this.db.execute("PRAGMA journal_mode=WAL;"); - - // Run migrations - await this.runMigrations(); - - this.initialized = true; - logger.log( - "[ElectronPlatformService] SQLite database initialized successfully", - ); - } catch (error) { - logger.error( - "[ElectronPlatformService] Error initializing SQLite database:", - error, - ); - throw new Error( - "[ElectronPlatformService] Failed to initialize database", - ); - } - } - - private async runMigrations(): Promise { - if (!this.db) { - throw new Error("Database not initialized"); - } - - // Create migrations table if it doesn't exist - await this.db.execute(` - CREATE TABLE IF NOT EXISTS migrations ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL UNIQUE, - executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); - `); - - // Get list of executed migrations - const result = await this.db.query("SELECT name FROM migrations;"); - const executedMigrations = new Set( - result.values?.map((row) => row[0]) || [], - ); - - // Run pending migrations in order - const migrations: Migration[] = [ - { - name: "001_initial", - sql: ` - CREATE TABLE IF NOT EXISTS accounts ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - dateCreated TEXT NOT NULL, - derivationPath TEXT, - did TEXT NOT NULL, - identityEncrBase64 TEXT, - mnemonicEncrBase64 TEXT, - passkeyCredIdHex TEXT, - publicKeyHex TEXT NOT NULL - ); - - CREATE INDEX IF NOT EXISTS idx_accounts_did ON accounts(did); - - CREATE TABLE IF NOT EXISTS secret ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - secretBase64 TEXT NOT NULL - ); - - CREATE TABLE IF NOT EXISTS settings ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - accountDid TEXT, - activeDid TEXT, - apiServer TEXT, - filterFeedByNearby BOOLEAN, - filterFeedByVisible BOOLEAN, - finishedOnboarding BOOLEAN, - firstName TEXT, - hideRegisterPromptOnNewContact BOOLEAN, - isRegistered BOOLEAN, - lastName TEXT, - lastAckedOfferToUserJwtId TEXT, - lastAckedOfferToUserProjectsJwtId TEXT, - lastNotifiedClaimId TEXT, - lastViewedClaimId TEXT, - notifyingNewActivityTime TEXT, - notifyingReminderMessage TEXT, - notifyingReminderTime TEXT, - partnerApiServer TEXT, - passkeyExpirationMinutes INTEGER, - profileImageUrl TEXT, - searchBoxes TEXT, - showContactGivesInline BOOLEAN, - showGeneralAdvanced BOOLEAN, - showShortcutBvc BOOLEAN, - vapid TEXT, - warnIfProdServer BOOLEAN, - warnIfTestServer BOOLEAN, - webPushServer TEXT - ); - - CREATE INDEX IF NOT EXISTS idx_settings_accountDid ON settings(accountDid); - - INSERT INTO settings (id, apiServer) VALUES (1, '${DEFAULT_ENDORSER_API_SERVER}'); - - CREATE TABLE IF NOT EXISTS contacts ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - did TEXT NOT NULL, - name TEXT, - contactMethods TEXT, - nextPubKeyHashB64 TEXT, - notes TEXT, - profileImageUrl TEXT, - publicKeyBase64 TEXT, - seesMe BOOLEAN, - registered BOOLEAN - ); - - CREATE INDEX IF NOT EXISTS idx_contacts_did ON contacts(did); - CREATE INDEX IF NOT EXISTS idx_contacts_name ON contacts(name); - - CREATE TABLE IF NOT EXISTS logs ( - date TEXT PRIMARY KEY, - message TEXT NOT NULL - ); - - CREATE TABLE IF NOT EXISTS temp ( - id TEXT PRIMARY KEY, - blobB64 TEXT - ); - `, - }, - ]; - - for (const migration of migrations) { - if (!executedMigrations.has(migration.name)) { - await this.db.execute(migration.sql); - await this.db.run("INSERT INTO migrations (name) VALUES (?)", [ - migration.name, - ]); - logger.log(`Migration ${migration.name} executed successfully`); - } - } - } - - /** - * Gets the capabilities of the Electron platform - * @returns Platform capabilities object - */ - getCapabilities(): PlatformCapabilities { - return { - hasFileSystem: false, // Not implemented yet - hasCamera: false, // Not implemented yet - isMobile: false, - isIOS: false, - hasFileDownload: false, // Not implemented yet - needsFileHandlingInstructions: false, - isNativeApp: true, // Electron is a native app - }; - } - - /** - * Reads a file from the filesystem. - * @param _path - Path to the file to read - * @returns Promise that should resolve to file contents - * @throws Error with "Not implemented" message - * @todo Implement file reading using Electron's file system API - */ - async readFile(_path: string): Promise { - throw new Error("Not implemented"); - } - - /** - * Writes content to a file. - * @param _path - Path where to write the file - * @param _content - Content to write to the file - * @throws Error with "Not implemented" message - * @todo Implement file writing using Electron's file system API - */ - async writeFile(_path: string, _content: string): Promise { - throw new Error("Not implemented"); - } - - /** - * Writes content to a file and opens the system share dialog. - * @param _fileName - Name of the file to create - * @param _content - Content to write to the file - * @throws Error with "Not implemented" message - * @todo Implement using Electron's dialog and file system APIs - */ - async writeAndShareFile(_fileName: string, _content: string): Promise { - throw new Error("Not implemented"); - } - - /** - * Deletes a file from the filesystem. - * @param _path - Path to the file to delete - * @throws Error with "Not implemented" message - * @todo Implement file deletion using Electron's file system API - */ - async deleteFile(_path: string): Promise { - throw new Error("Not implemented"); - } - - /** - * Lists files in the specified directory. - * @param _directory - Path to the directory to list - * @returns Promise that should resolve to array of filenames - * @throws Error with "Not implemented" message - * @todo Implement directory listing using Electron's file system API - */ - async listFiles(_directory: string): Promise { - throw new Error("Not implemented"); - } - - /** - * Should open system camera to take a picture. - * @returns Promise that should resolve to captured image data - * @throws Error with "Not implemented" message - * @todo Implement camera access using Electron's media APIs - */ - async takePicture(): Promise { - logger.error("takePicture not implemented in Electron platform"); - throw new Error("Not implemented"); - } - - /** - * Should open system file picker for selecting an image. - * @returns Promise that should resolve to selected image data - * @throws Error with "Not implemented" message - * @todo Implement file picker using Electron's dialog API - */ - async pickImage(): Promise { - logger.error("pickImage not implemented in Electron platform"); - throw new Error("Not implemented"); - } - - /** - * Should handle deep link URLs for the desktop application. - * @param _url - The deep link URL to handle - * @throws Error with "Not implemented" message - * @todo Implement deep link handling using Electron's protocol handler - */ - async handleDeepLink(_url: string): Promise { - logger.error("handleDeepLink not implemented in Electron platform"); - throw new Error("Not implemented"); - } - - /** - * @see PlatformService.dbQuery - */ - async dbQuery(sql: string, params?: unknown[]): Promise { - await this.initializeDatabase(); - if (!this.db) { - throw new Error("Database not initialized"); - } - - try { - const result = await this.db.query(sql, params || []); - const values = result.values || []; - return { - columns: [], // SQLite plugin doesn't provide column names in query result - values: values as SqlValue[][], - }; - } catch (error) { - logger.error("Error executing query:", error); - throw new Error( - `Database query failed: ${error instanceof Error ? error.message : String(error)}`, - ); - } - } - - /** - * @see PlatformService.dbExec - */ - async dbExec( - sql: string, - params?: unknown[], - ): Promise<{ changes: number; lastId?: number }> { - await this.initializeDatabase(); - if (!this.db) { - throw new Error("Database not initialized"); - } - - try { - const result = await this.db.run(sql, params || []); - const changes = result.changes as Changes; - return { - changes: changes?.changes || 0, - lastId: changes?.lastId, - }; - } catch (error) { - logger.error("Error executing statement:", error); - throw new Error( - `Database execution failed: ${error instanceof Error ? error.message : String(error)}`, - ); - } - } - - /** - * 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 { - throw new Error("Camera rotation not implemented in Electron platform"); - } -} diff --git a/tsconfig.electron.json b/tsconfig.electron.json deleted file mode 100644 index c667c18e..00000000 --- a/tsconfig.electron.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "module": "ESNext", - "moduleResolution": "bundler", - "target": "ES2020", - "outDir": "dist-electron", - "rootDir": "src", - "sourceMap": true, - "esModuleInterop": true, - "allowJs": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "allowImportingTsExtensions": true, - "types": ["vite/client"], - "paths": { - "@/*": ["./src/*"] - }, - "typeRoots": ["./node_modules/@types", "./src/types"] - }, - "include": [ - "src/**/*.ts", - "src/**/*.d.ts", - "src/**/*.tsx", - "src/**/*.vue" - ] -} \ No newline at end of file diff --git a/vite.config.common.mts b/vite.config.common.mts index 8d7cb0ee..38f216b9 100644 --- a/vite.config.common.mts +++ b/vite.config.common.mts @@ -13,28 +13,27 @@ const __dirname = path.dirname(__filename); export async function createBuildConfig(mode: string): Promise { const appConfig = await loadAppConfig(); - const isElectron = mode === "electron"; const isCapacitor = mode === "capacitor"; - const isNative = isElectron || isCapacitor; + const isNative = isCapacitor; - // Explicitly set platform and disable PWA for Electron + // Set platform and disable PWA for native platforms process.env.VITE_PLATFORM = mode; - process.env.VITE_PWA_ENABLED = isElectron ? 'false' : 'true'; - process.env.VITE_DISABLE_PWA = isElectron ? 'true' : 'false'; + process.env.VITE_PWA_ENABLED = isCapacitor ? 'false' : 'true'; + process.env.VITE_DISABLE_PWA = isCapacitor ? 'true' : 'false'; - if (isElectron || isCapacitor) { + if (isCapacitor) { process.env.VITE_PWA_ENABLED = 'false'; } return { - base: isElectron ? "./" : "/", + base: "/", plugins: [vue()], server: { port: parseInt(process.env.VITE_PORT || "8080"), fs: { strict: false }, }, build: { - outDir: isElectron ? "dist-electron" : "dist", + outDir: "dist", assetsDir: 'assets', chunkSizeWarningLimit: 1000, rollupOptions: { @@ -57,9 +56,9 @@ export async function createBuildConfig(mode: string): Promise { define: { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), 'process.env.VITE_PLATFORM': JSON.stringify(mode), - 'process.env.VITE_PWA_ENABLED': JSON.stringify(!isElectron), - 'process.env.VITE_DISABLE_PWA': JSON.stringify(isElectron), - __dirname: isElectron ? JSON.stringify(process.cwd()) : '""', + 'process.env.VITE_PWA_ENABLED': JSON.stringify(!isCapacitor), + 'process.env.VITE_DISABLE_PWA': JSON.stringify(isCapacitor), + __dirname: JSON.stringify(process.cwd()), __IS_MOBILE__: JSON.stringify(isCapacitor), __USE_QR_READER__: JSON.stringify(!isCapacitor), 'process.platform': JSON.stringify('browser'), @@ -88,7 +87,7 @@ export async function createBuildConfig(mode: string): Promise { '@nostr/tools', '@nostr/tools/nip06', ], - exclude: isElectron ? [ + exclude: isCapacitor ? [ 'register-service-worker', 'workbox-window', 'web-push', diff --git a/vite.config.electron.mts b/vite.config.electron.mts deleted file mode 100644 index b4d22c68..00000000 --- a/vite.config.electron.mts +++ /dev/null @@ -1,154 +0,0 @@ -import { defineConfig, mergeConfig } from "vite"; -import { createBuildConfig } from "./vite.config.common.mts"; -import path from 'path'; - -export default defineConfig(async () => { - const baseConfig = await createBuildConfig('electron'); - - return mergeConfig(baseConfig, { - build: { - outDir: 'dist-electron', - rollupOptions: { - input: { - // Main process entry points - main: path.resolve(__dirname, 'src/electron/main.ts'), - preload: path.resolve(__dirname, 'src/electron/preload.js'), - // Renderer process entry point (the web app) - app: path.resolve(__dirname, 'index.html'), - }, - external: ['electron'], - output: { - format: 'cjs', - entryFileNames: (chunkInfo) => { - // Use different formats for main process vs renderer - if (chunkInfo.name === 'main' || chunkInfo.name === 'preload') { - return '[name].js'; - } - return 'assets/[name].[hash].js'; - }, - assetFileNames: (assetInfo) => { - // Keep main process files in root, others in assets - if (assetInfo.name === 'main.js' || assetInfo.name === 'preload.js') { - return '[name].[ext]'; - } - return 'assets/[name].[hash].[ext]'; - }, - chunkFileNames: 'assets/[name].[hash].js', - }, - }, - target: 'node18', - minify: false, - sourcemap: true, - }, - resolve: { - alias: { - '@': path.resolve(__dirname, 'src'), - }, - }, - optimizeDeps: { - include: ['@/utils/logger'] - }, - plugins: [ - { - name: 'typescript-transform', - transform(code: string, id: string) { - if (id.endsWith('main.ts')) { - // Replace the logger import with inline logger - return code.replace( - /import\s*{\s*logger\s*}\s*from\s*['"]@\/utils\/logger['"];?/, - `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), - };` - ); - } - return code; - } - }, - { - name: 'remove-sw-imports', - transform(code: string, id: string) { - // Remove service worker imports and registrations - if (id.includes('registerServiceWorker') || - id.includes('register-service-worker') || - id.includes('sw_scripts') || - id.includes('PushNotificationPermission') || - code.includes('navigator.serviceWorker')) { - return { - code: code - .replace(/import.*registerServiceWorker.*$/mg, '') - .replace(/import.*register-service-worker.*$/mg, '') - .replace(/navigator\.serviceWorker/g, 'undefined') - .replace(/if\s*\([^)]*serviceWorker[^)]*\)\s*{[^}]*}/g, '') - .replace(/import.*workbox.*$/mg, '') - .replace(/importScripts\([^)]*\)/g, '') - }; - } - return code; - } - }, - { - name: 'remove-sw-files', - enforce: 'pre', - resolveId(id: string) { - // Prevent service worker files from being included - if (id.includes('sw.js') || - id.includes('workbox') || - id.includes('registerSW.js') || - id.includes('manifest.webmanifest')) { - return '\0empty'; - } - return null; - }, - load(id: string) { - if (id === '\0empty') { - return 'export default {}'; - } - return null; - } - }, - { - name: 'electron-css-injection', - enforce: 'post', - generateBundle(options, bundle) { - // Find the main CSS file - const cssAsset = Object.values(bundle).find( - (asset: any) => asset.type === 'asset' && asset.fileName?.endsWith('.css') - ) as any; - - if (cssAsset) { - // Find the HTML file and inject CSS link - const htmlAsset = Object.values(bundle).find( - (asset: any) => asset.type === 'asset' && asset.fileName?.endsWith('.html') - ) as any; - - if (htmlAsset) { - const cssHref = `./${cssAsset.fileName}`; - const cssLink = ` \n`; - - // Check if CSS link already exists - if (!htmlAsset.source.includes(cssHref)) { - // Inject CSS link after the title tag - htmlAsset.source = htmlAsset.source.replace( - /(.*?<\/title>)/, - `$1\n${cssLink}` - ); - console.log(`[electron-css-injection] Injected CSS link: ${cssHref}`); - } else { - console.log(`[electron-css-injection] CSS link already present: ${cssHref}`); - } - } - } - } - } - ], - ssr: { - noExternal: ['@/utils/logger'] - }, - base: './', - publicDir: 'public', - }); -}); \ No newline at end of file diff --git a/vite.config.electron.renderer.mts b/vite.config.electron.renderer.mts deleted file mode 100644 index 9e0f7b36..00000000 --- a/vite.config.electron.renderer.mts +++ /dev/null @@ -1,31 +0,0 @@ -import { defineConfig } from 'vite'; -import vue from '@vitejs/plugin-vue'; -import path from 'path'; - -export default defineConfig({ - plugins: [vue()], - base: './', - resolve: { - alias: { - '@': path.resolve(__dirname, 'src'), - }, - }, - build: { - outDir: 'dist-electron/www', - emptyOutDir: false, - assetsDir: 'assets', - cssCodeSplit: false, - rollupOptions: { - input: path.resolve(__dirname, 'src/main.electron.ts'), - output: { - entryFileNames: 'main.electron.js', - assetFileNames: 'assets/[name]-[hash][extname]', - chunkFileNames: 'assets/[name]-[hash].js', - manualChunks: undefined - } - }, - commonjsOptions: { - transformMixedEsModules: true - } - } -}); \ No newline at end of file