refactor: implement database-specific schema architecture with schema-as-query pattern

🏗️ **Major Database Schema Refactoring**

**Problem Solved**: Eliminated model duplication and multiple sources of truth by:
- Removed duplicate models (`internal/models/content.go`)
- Replaced inlined schema strings with sqlc-generated setup functions
- Implemented database-specific schemas with proper NOT NULL constraints

**Key Improvements**:
 **Single Source of Truth**: Database schemas define all types, no manual sync needed
 **Clean Generated Types**: sqlc generates `string` and `int64` instead of `sql.NullString/sql.NullTime`
 **Schema-as-Query Pattern**: Setup functions generated by sqlc for type safety
 **Database-Specific Optimization**: SQLite INTEGER timestamps, PostgreSQL BIGINT timestamps
 **Cross-Database Compatibility**: Single codebase supports both SQLite and PostgreSQL

**Architecture Changes**:
- `db/sqlite/` - SQLite-specific schema and setup queries
- `db/postgresql/` - PostgreSQL-specific schema and setup queries
- `db/queries/` - Cross-database CRUD queries using `sqlc.arg()` syntax
- `internal/db/database.go` - Database abstraction with runtime selection
- `internal/api/models.go` - Clean API models for requests/responses

**Version Control System**: Complete element-level history with user attribution and rollback

**Verification**:  Full API workflow tested (create → update → rollback → versions)
**Production Ready**: Supports SQLite (development) → PostgreSQL (production) migration
This commit is contained in:
2025-09-09 00:25:07 +02:00
parent 161c320304
commit bab329b429
41 changed files with 3703 additions and 561 deletions

View File

@@ -1,158 +1,123 @@
# Insertr Content Server
The HTTP API server that provides content storage and retrieval for the Insertr CMS system.
REST API server for the Insertr CMS system. Provides content management with version control and user attribution.
## 🚀 Quick Start
## Features
### Build and Run
```bash
# Build the server
go build -o insertr-server ./cmd/server
- **Content Management**: Full CRUD operations for content items
- **Version Control**: Complete edit history with rollback functionality
- **User Attribution**: Track who made each change
- **Type-Safe Database**: Uses sqlc for generated Go code from SQL
- **SQLite & PostgreSQL**: Database flexibility for development to production
# Start with default settings
./insertr-server
## API Endpoints
# Start with custom port and database
./insertr-server --port 8080 --db ./content.db
```
### Development
```bash
# Install dependencies
go mod tidy
# Run directly with go
go run ./cmd/server --port 8080
```
## 📊 API Endpoints
The server implements the exact API contract expected by both the Go CLI client and JavaScript browser client:
### Content Retrieval
### Content Operations
- `GET /api/content?site_id={site}` - Get all content for a site
- `GET /api/content/{id}?site_id={site}` - Get single content item
- `GET /api/content/bulk?site_id={site}&ids[]={id1}&ids[]={id2}` - Get multiple items
### Content Modification
- `GET /api/content/bulk?site_id={site}&ids[]={id1}&ids[]={id2}` - Get multiple content items
- `POST /api/content` - Create new content
- `PUT /api/content/{id}?site_id={site}` - Update existing content
- `PUT /api/content/{id}?site_id={site}` - Update existing content
- `DELETE /api/content/{id}?site_id={site}` - Delete content
### System
- `GET /health` - Health check endpoint
### Version Control
- `GET /api/content/{id}/versions?site_id={site}` - Get version history
- `POST /api/content/{id}/rollback?site_id={site}` - Rollback to specific version
## 🗄️ Database
### Health & Status
- `GET /health` - Server health check
Uses SQLite by default for simplicity. The database schema:
## User Attribution
```sql
CREATE TABLE content (
id TEXT NOT NULL,
site_id TEXT NOT NULL,
value TEXT NOT NULL,
type TEXT NOT NULL CHECK (type IN ('text', 'markdown', 'link')),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id, site_id)
);
All content operations support user attribution via the `X-User-ID` header:
```bash
curl -X PUT "http://localhost:8080/api/content/hero-title?site_id=demo" \
-H "Content-Type: application/json" \
-H "X-User-ID: john@example.com" \
-d '{"value": "Updated content"}'
```
## 🔧 Configuration
## Quick Start
### Command Line Options
- `--port` - Server port (default: 8080)
- `--db` - SQLite database path (default: ./insertr.db)
```bash
# Build server
go build -o insertr-server ./cmd/server
### CORS
Currently configured for development with `Access-Control-Allow-Origin: *`.
For production, configure CORS appropriately.
# Start server
./insertr-server --port 8080
## 🧪 Testing
# Check health
curl http://localhost:8080/health
```
### API Testing Examples
## Development
### Using sqlc
```bash
# Install sqlc
go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
# Generate Go code from SQL
sqlc generate
# Build with generated code
go build ./cmd/server
```
### Database Schema
See `db/schema/schema.sql` for the complete schema. Key tables:
- `content` - Current content versions
- `content_versions` - Complete version history
### Example Version Control Workflow
```bash
# Create content
curl -X POST "http://localhost:8080/api/content" \
-H "Content-Type: application/json" \
-d '{"id":"hero-title","value":"Welcome!","type":"text"}'
-H "X-User-ID: alice@example.com" \
-d '{
"id": "hero-title",
"site_id": "demo",
"value": "Original Title",
"type": "text"
}'
# Get content
curl "http://localhost:8080/api/content/hero-title?site_id=demo"
# Update content
# Update content (creates version)
curl -X PUT "http://localhost:8080/api/content/hero-title?site_id=demo" \
-H "Content-Type: application/json" \
-d '{"value":"Updated Welcome!"}'
-H "X-User-ID: bob@example.com" \
-d '{"value": "Updated Title"}'
# View version history
curl "http://localhost:8080/api/content/hero-title/versions?site_id=demo"
# Rollback to version 1
curl -X POST "http://localhost:8080/api/content/hero-title/rollback?site_id=demo" \
-H "Content-Type: application/json" \
-H "X-User-ID: admin@example.com" \
-d '{"version_id": 1}'
```
### Integration Testing
```bash
# From project root
./test-integration.sh
```
## 🏗️ Architecture Integration
This server bridges the gap between:
1. **Browser Editor** (`lib/`) - JavaScript client that saves edits
2. **CLI Enhancement** (`insertr-cli/`) - Go client that pulls content during builds
3. **Static Site Generation** - Enhanced HTML with database content
### Content Flow
```
Browser Edit → HTTP Server → SQLite Database
CLI Build Process ← HTTP Server ← SQLite Database
Enhanced Static Site
```
## 🚀 Production Deployment
### Docker (Recommended)
```dockerfile
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o insertr-server ./cmd/server
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/insertr-server .
EXPOSE 8080
CMD ["./insertr-server"]
```
## Configuration
### Environment Variables
- `PORT` - Server port
- `DB_PATH` - Database file path
- `CORS_ORIGIN` - Allowed CORS origin for production
- `PORT` - Server port (default: 8080)
- `DB_PATH` - SQLite database file path (default: ./insertr.db)
### Health Monitoring
The `/health` endpoint returns JSON status for monitoring:
```json
{"status":"healthy","service":"insertr-server"}
### Command Line Flags
```bash
./insertr-server --help
```
## 🔐 Security Considerations
## Production Deployment
### Current State (Development)
- Open CORS policy
- No authentication required
- SQLite database (single file)
### Production TODO
- [ ] JWT/OAuth authentication
- [ ] PostgreSQL database option
- [ ] Rate limiting
- [ ] Input validation and sanitization
- [ ] HTTPS enforcement
- [ ] Configurable CORS origins
---
**Status**: ✅ Fully functional development server
**Next**: Production hardening and authentication
1. **Database**: Consider PostgreSQL for production scale
2. **Authentication**: Integrate with your auth system via middleware
3. **CORS**: Configure appropriate CORS policies
4. **SSL**: Serve over HTTPS
5. **Monitoring**: Add logging and metrics collection