Files
2026-08-06 11:16:47 +02:00

143 lines
3.7 KiB
Markdown

# Carry Your Live - Backend API
REST API for the Carry Your Live task management app with offline-first sync support.
## Tech Stack
- **Runtime**: Node.js 20+ with TypeScript
- **Framework**: Express.js
- **Database**: PostgreSQL with Drizzle ORM
- **Authentication**: JWT (JSON Web Tokens)
- **Validation**: Zod
## Quick Start
### Option A — Docker (Postgres + API in containers)
Requires Docker. Runs the database **and** the Node API together:
```bash
docker compose up --build
```
This starts:
- `carry-your-live-db` — PostgreSQL 16 on port 5432
- `carry-your-live-api` — the API in dev mode (tsx watch, hot reload) on port 3000, schema auto-applied on start
Server runs at `http://localhost:3000` (health check: `GET /health`).
For production-style serving of the built app:
```bash
# Build and run the slim prod image instead
docker build --target prod -t carry-your-live-api:prod .
docker run --rm -p 3000:3000 --env-file .env carry-your-live-api:prod
```
### Option B — Local Node + Docker Postgres
### Prerequisites
- Node.js 20+
- PostgreSQL 16+ (or use Docker)
### Setup
1. **Start PostgreSQL** (using Docker):
```bash
docker-compose up -d postgres
```
2. **Install dependencies**:
```bash
npm install
```
3. **Configure environment**:
```bash
cp .env.example .env
# Edit .env with your settings
```
4. **Run database migrations**:
```bash
npm run db:push
```
5. **Start development server**:
```bash
npm run dev
```
Server runs at `http://localhost:3000`
## API Endpoints
### Authentication
- `POST /api/auth/register` - Register new user
- `POST /api/auth/login` - Login
- `GET /api/auth/me` - Get current user
### Categories
- `GET /api/categories` - List categories
- `POST /api/categories` - Create category
- `PATCH /api/categories/:id` - Update category
- `DELETE /api/categories/:id` - Delete category
### Tasks
- `GET /api/tasks` - List tasks (with filters)
- `GET /api/tasks/:id` - Get task with subtasks
- `POST /api/tasks` - Create task
- `PATCH /api/tasks/:id` - Update task
- `DELETE /api/tasks/:id` - Delete task
- `POST /api/tasks/batch` - Batch operations
### Subtasks
- `GET /api/subtasks/task/:taskId` - List subtasks for task
- `POST /api/subtasks/task/:taskId` - Create subtask
- `PATCH /api/subtasks/:id` - Update subtask
- `DELETE /api/subtasks/:id` - Delete subtask
### Users
- `GET /api/users/me` - Get user with settings
- `PATCH /api/users/me/settings` - Update settings
### Sync (Offline-first)
- `GET /api/sync?since=<timestamp>` - Pull changes since timestamp
- `POST /api/sync/push` - Push local changes
## Database Schema
See `src/db/schema.ts` for Drizzle schema definitions.
## Sync Protocol
The sync endpoint uses a cursor-based approach:
1. **Pull**: Client sends `since` timestamp, server returns all changes since then
2. **Push**: Client sends batched changes with `lastPulledAt`, server applies with conflict resolution (last-write-wins)
## Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `DATABASE_URL` | PostgreSQL connection string | Required |
| `JWT_SECRET` | Secret for JWT signing | Required (32+ chars) |
| `PORT` | Server port | 3000 |
| `NODE_ENV` | Environment | development |
| `FRONTEND_URL` | CORS origin | http://localhost:8081 |
## Production Deployment
1. Set `NODE_ENV=production`
2. Use strong `JWT_SECRET` (32+ random chars)
3. Configure proper `DATABASE_URL`
4. Run `npm run build` then `npm start`
5. Use process manager (PM2, systemd) or container orchestration
The included `Dockerfile` has a `prod` stage that builds TypeScript and serves `dist/`
with production-only dependencies on a minimal `node:20-alpine` image.
## License
MIT