Add comprehensive README documentation
- Describe project purpose and features - Document tech stack (Bun, Elysia, SvelteKit, SQLite, Drizzle) - Add project structure overview - Include setup and installation instructions - Document all API endpoints - Include database schema for all tables - Explain background job queue system - Document LoTW sync logic and pagination features - Add development commands Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
254
README.md
254
README.md
@@ -1,15 +1,255 @@
|
||||
# award
|
||||
# Ham Radio Award Portal
|
||||
|
||||
To install dependencies:
|
||||
A web application for amateur radio operators to track QSOs (contacts) and award progress using Logbook of the World (LoTW) data.
|
||||
|
||||
## Features
|
||||
|
||||
- **User Authentication**: Register and login with callsign, email, and password
|
||||
- **LoTW Integration**: Sync QSOs from ARRL's Logbook of the World
|
||||
- Background job queue for non-blocking sync operations
|
||||
- Incremental sync using last confirmation date
|
||||
- Wavelog-compatible download logic with proper validation
|
||||
- One sync job per user enforcement
|
||||
- **QSO Log**: View and manage confirmed QSOs
|
||||
- Pagination support for large QSO collections
|
||||
- Filter by band, mode, and confirmation status
|
||||
- Statistics dashboard (total QSOs, confirmed, DXCC entities, bands)
|
||||
- Delete all QSOs with confirmation
|
||||
- **Settings**: Configure LoTW credentials securely
|
||||
|
||||
## Tech Stack
|
||||
|
||||
### Backend
|
||||
- **Runtime**: Bun
|
||||
- **Framework**: Elysia.js
|
||||
- **Database**: SQLite with Drizzle ORM
|
||||
- **Authentication**: JWT tokens
|
||||
|
||||
### Frontend
|
||||
- **Framework**: SvelteKit
|
||||
- **Language**: JavaScript
|
||||
- **Styling**: Custom CSS
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
award/
|
||||
├── src/
|
||||
│ ├── backend/
|
||||
│ │ ├── config/
|
||||
│ │ │ ├── database.js # Database connection
|
||||
│ │ │ └── jwt.js # JWT configuration
|
||||
│ │ ├── db/
|
||||
│ │ │ └── schema/
|
||||
│ │ │ └── index.js # Database schema (users, qsos, sync_jobs)
|
||||
│ │ ├── services/
|
||||
│ │ │ ├── auth.service.js # User authentication
|
||||
│ │ │ ├── lotw.service.js # LoTW sync & QSO management
|
||||
│ │ │ └── job-queue.service.js # Background job queue
|
||||
│ │ └── index.js # API routes and server
|
||||
│ └── frontend/
|
||||
│ ├── src/
|
||||
│ │ ├── lib/
|
||||
│ │ │ ├── api.js # API client
|
||||
│ │ │ └── stores.js # Svelte stores (auth)
|
||||
│ │ └── routes/
|
||||
│ │ ├── +page.svelte # Main menu
|
||||
│ │ ├── login/+page.svelte # Login page
|
||||
│ │ ├── register/+page.svelte # Registration page
|
||||
│ │ ├── qsos/+page.svelte # QSO log with pagination
|
||||
│ │ └── settings/+page.svelte # Settings & LoTW credentials
|
||||
│ └── package.json
|
||||
├── award.db # SQLite database (auto-created)
|
||||
├── drizzle.config.js # Drizzle ORM configuration
|
||||
├── package.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
### Prerequisites
|
||||
- [Bun](https://bun.sh) v1.3.6 or later
|
||||
|
||||
### Installation
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd award
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run:
|
||||
|
||||
```bash
|
||||
bun run index.ts
|
||||
3. Set up environment variables (optional):
|
||||
Create a `.env` file in the project root:
|
||||
```env
|
||||
JWT_SECRET=your-secret-key-here
|
||||
```
|
||||
|
||||
This project was created using `bun init` in bun v1.3.6. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
||||
If not provided, a default secret will be used.
|
||||
|
||||
4. Initialize the database:
|
||||
```bash
|
||||
bun run db:push
|
||||
```
|
||||
|
||||
This creates the SQLite database with required tables (users, qsos, sync_jobs).
|
||||
|
||||
## Running the Application
|
||||
|
||||
Start both backend and frontend:
|
||||
|
||||
```bash
|
||||
# Start backend (port 3001)
|
||||
bun run backend/index.js
|
||||
|
||||
# Start frontend (port 5173)
|
||||
cd src/frontend && bun run dev
|
||||
```
|
||||
|
||||
Or use the convenience scripts:
|
||||
```bash
|
||||
# Backend only
|
||||
bun run backend
|
||||
|
||||
# Frontend only
|
||||
bun run frontend
|
||||
```
|
||||
|
||||
The application will be available at:
|
||||
- Frontend: http://localhost:5173
|
||||
- Backend API: http://localhost:3001
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Authentication
|
||||
- `POST /api/auth/register` - Register new user
|
||||
- `POST /api/auth/login` - Login user
|
||||
- `GET /api/auth/me` - Get current user profile
|
||||
- `PUT /api/auth/lotw-credentials` - Update LoTW credentials
|
||||
|
||||
### LoTW Sync
|
||||
- `POST /api/lotw/sync` - Queue a LoTW sync job (returns job ID)
|
||||
|
||||
### Jobs
|
||||
- `GET /api/jobs/:jobId` - Get job status
|
||||
- `GET /api/jobs/active` - Get user's active job
|
||||
- `GET /api/jobs` - Get recent jobs (query: `?limit=10`)
|
||||
|
||||
### QSOs
|
||||
- `GET /api/qsos` - Get user's QSOs with pagination
|
||||
- Query parameters: `?page=1&limit=100&band=20m&mode=CW&confirmed=true`
|
||||
- `GET /api/qsos/stats` - Get QSO statistics
|
||||
- `DELETE /api/qsos/all` - Delete all QSOs (requires confirmation)
|
||||
|
||||
### Health
|
||||
- `GET /api/health` - Health check endpoint
|
||||
|
||||
## Database Schema
|
||||
|
||||
### Users Table
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
callsign TEXT NOT NULL,
|
||||
lotwUsername TEXT,
|
||||
lotwPassword TEXT,
|
||||
createdAt TEXT NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
### QSOs Table
|
||||
```sql
|
||||
CREATE TABLE qsos (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
userId INTEGER NOT NULL,
|
||||
callsign TEXT NOT NULL,
|
||||
qsoDate TEXT NOT NULL,
|
||||
timeOn TEXT NOT NULL,
|
||||
band TEXT,
|
||||
mode TEXT,
|
||||
entity TEXT,
|
||||
grid TEXT,
|
||||
lotwQslRstatus TEXT,
|
||||
lotwQslRdate TEXT,
|
||||
FOREIGN KEY (userId) REFERENCES users(id)
|
||||
);
|
||||
```
|
||||
|
||||
### Sync Jobs Table
|
||||
```sql
|
||||
CREATE TABLE sync_jobs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
userId INTEGER NOT NULL,
|
||||
status TEXT NOT NULL, -- pending, running, completed, failed
|
||||
type TEXT NOT NULL, -- lotw_sync
|
||||
startedAt INTEGER,
|
||||
completedAt INTEGER,
|
||||
result TEXT, -- JSON
|
||||
error TEXT,
|
||||
createdAt INTEGER NOT NULL,
|
||||
FOREIGN KEY (userId) REFERENCES users(id)
|
||||
);
|
||||
```
|
||||
|
||||
## Features in Detail
|
||||
|
||||
### Background Job Queue
|
||||
|
||||
The application uses an in-memory job queue system for async operations:
|
||||
- Jobs are persisted to database for recovery
|
||||
- Only one active job per user (enforced at queue level)
|
||||
- Status tracking: pending → running → completed/failed
|
||||
- Real-time progress updates via job result field
|
||||
- Client polls job status every 2 seconds
|
||||
|
||||
### LoTW Sync Logic
|
||||
|
||||
Following Wavelog's proven approach:
|
||||
1. **First sync**: Uses date `2000-01-01` to retrieve all QSOs
|
||||
2. **Subsequent syncs**: Uses `MAX(lotwQslRdate)` from database
|
||||
3. **Validation**:
|
||||
- Checks for "Username/password incorrect" in response
|
||||
- Validates file starts with "ARRL Logbook of the World Status Report"
|
||||
4. **Timeout handling**: 30-second connection timeout
|
||||
5. **Query parameters**: Matches Wavelog's LoTW download
|
||||
|
||||
### Pagination
|
||||
|
||||
- Default page size: 100 QSOs per page
|
||||
- Supports custom page size via `limit` parameter
|
||||
- Shows page numbers with ellipsis for large page counts
|
||||
- Displays "Showing X-Y of Z" info
|
||||
- Previous/Next navigation buttons
|
||||
|
||||
## Development
|
||||
|
||||
### Database Migrations
|
||||
|
||||
```bash
|
||||
# Push schema changes to database
|
||||
bun run db:push
|
||||
|
||||
# Open Drizzle Studio (database GUI)
|
||||
bun run db:studio
|
||||
```
|
||||
|
||||
### Linting
|
||||
|
||||
```bash
|
||||
bun run lint
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Credits
|
||||
|
||||
- LoTW integration inspired by [Wavelog](https://github.com/magicbug/CloudLog)
|
||||
- Built with [Bun](https://bun.sh), [Elysia](https://elysiajs.com), and [SvelteKit](https://kit.svelte.dev)
|
||||
|
||||
Reference in New Issue
Block a user