# Fahrtenbuch - Multi-Target Scala.js Application A collaborative trip tracking application built with Scala.js, supporting both browser and Node.js environments with real-time peer-to-peer synchronization. ## Architecture This project uses a multi-target architecture with shared business logic and platform-specific implementations: ``` fahrtenbuch/ ├── shared/ # Shared business logic and models │ └── src/main/scala/fahrtenbuch/ │ ├── model/ # Data models (Entry, EntryId) │ ├── core/ # Business logic (EntryManager) │ ├── storage/ # Storage interface │ └── sync/ # Synchronization interface ├── browser/ # Browser-specific implementation │ └── src/main/scala/fahrtenbuch/ │ ├── components/ # Laminar UI components │ ├── storage/ # Dexie (IndexedDB) storage │ ├── sync/ # Trystero (WebRTC) sync │ └── BrowserMain.scala ├── nodejs/ # Node.js-specific implementation │ └── src/main/scala/fahrtenbuch/ │ ├── storage/ # File system storage │ ├── sync/ # WebSocket sync │ └── NodeMain.scala └── dist/ # Build outputs ├── browser/ # Browser build artifacts └── nodejs/ # Node.js build artifacts ``` ## Features ### Shared Features - **CRDT-based synchronization**: Conflict-free replicated data types ensure consistent state across peers - **Real-time sync**: Changes are automatically synchronized between connected peers - **Offline support**: Works offline with automatic sync when reconnected - **Trip tracking**: Track vehicle trips with distance, cost calculations, and payment status ### Browser Features - **Modern UI**: Built with Laminar and Bulma CSS framework - **IndexedDB storage**: Persistent local storage using Dexie - **WebRTC P2P**: Direct peer-to-peer communication via Trystero - **Real-time updates**: Live UI updates as data changes ### Node.js Features - **Command-line interface**: Interactive CLI for managing entries - **File system storage**: JSON-based persistent storage - **WebSocket server**: Acts as a hub for peer communication - **Statistics reporting**: Built-in analytics and reporting ## Getting Started ### Prerequisites - **Scala**: 3.7.1 - **Node.js**: 16+ - **sbt**: 1.8+ ### Installation 1. Clone the repository: ```bash git clone cd fahrtenbuch ``` 2. Install dependencies: ```bash npm install ``` 3. Build both targets: ```bash npm run build ``` ## Development ### Browser Development ```bash # Start development server with hot reload npm run dev # Build browser version only npm run build:browser # Production build npm run build:browser:prod ``` ### Node.js Development ```bash # Build Node.js version npm run build:nodejs # Run Node.js application npm run start:nodejs # With custom options node dist/nodejs/main.js --port 8080 --data-dir ./data ``` ### SBT Commands ```bash # Compile shared code sbt sharedJs/compile # Fast build for browser sbt browser/fastOptJS # Optimized build for browser sbt browser/fullOptJS # Fast build for Node.js sbt nodejs/fastOptJS # Optimized build for Node.js sbt nodejs/fullOptJS # Build everything sbt compile ``` ## Usage ### Browser Application 1. Build and start the browser version: ```bash npm run build:browser npm run dev ``` 2. Open your browser and navigate to the displayed URL 3. Share the URL (including the hash) with other users for real-time collaboration ### Node.js Application 1. Build and start the Node.js version: ```bash npm run build:nodejs node dist/nodejs/main.js --port 8080 ``` 2. Use the interactive CLI: ``` fahrtenbuch> help fahrtenbuch> add 1000 1050 John Dog fahrtenbuch> list fahrtenbuch> stats fahrtenbuch> peers ``` 3. Connect multiple instances: ```bash # Start first instance node dist/nodejs/main.js --port 8080 # Start second instance and connect to first node dist/nodejs/main.js --port 8081 --connect localhost:8080 ``` ## Configuration ### Node.js Options - `--port `: WebSocket server port (default: 8080) - `--data-dir `: Data storage directory (default: ./data) - `--connect `: Connect to peer at host:port - `--help`: Show help message ### Browser Configuration The browser version uses URL fragments for room identification. Users sharing the same URL fragment will be connected in the same sync room. ## Data Model ### Entry Each trip entry contains: - `id`: Unique identifier - `startKm`: Starting odometer reading - `endKm`: Ending odometer reading - `driver`: Driver name - `animal`: Animal transported - `paid`: Payment status - `date`: Entry creation date - `gasPricePerKm`: Gas cost per kilometer - `wearPricePerKm`: Wear cost per kilometer ### Synchronization - Uses CRDT (Conflict-free Replicated Data Types) for conflict resolution - Last-writer-wins semantics for most fields - Automatic merging of concurrent updates - Peer-to-peer synchronization without central server ## Storage ### Browser Storage - **IndexedDB**: Via Dexie library - **Schema versioning**: Automatic migrations - **Live queries**: Real-time UI updates ### Node.js Storage - **File system**: JSON files in data directory - **Atomic writes**: Safe concurrent access - **Backup friendly**: Human-readable JSON format ## Networking ### Browser Networking - **WebRTC**: Direct peer-to-peer via Trystero - **TURN/STUN**: Configurable relay servers - **Room-based**: URL hash determines sync room ### Node.js Networking - **WebSocket**: Server-client architecture - **Auto-discovery**: Automatic peer detection - **Hub model**: Can act as relay for browser clients ## Development Tips ### Adding New Features 1. Add shared logic to `shared/src/main/scala/fahrtenbuch/` 2. Implement platform-specific parts in `browser/` and `nodejs/` 3. Update interfaces in `storage/` and `sync/` packages 4. Test both targets with `npm run build` ### Debugging - Browser: Use browser dev tools, network tab for WebRTC - Node.js: Use `console.log` or Node.js debugging tools - Storage: Check browser IndexedDB or Node.js data directory ### Performance - Use `fullOptJS` for production builds - Browser builds are optimized for incremental loading - Node.js builds are optimized for startup time ## Contributing 1. Fork the repository 2. Create a feature branch 3. Make changes to shared code and both platform implementations 4. Test both browser and Node.js targets 5. Submit a pull request ## License [Add your license here]