Skip to content

Commit 0a56d42

Browse files
committed
refactor: Restructure codebase into modular architecture with comprehensive testing
Major architectural improvements: - Reorganized code from monolithic index.ts into proper module structure - Separated concerns into controllers, services, middleware, and utilities - Added comprehensive unit and integration test suite (25 tests passing) - Implemented proper TypeScript configuration with strict mode New Structure: - src/config/: Application configuration and constants - src/controllers/: Request handlers for settings and health endpoints - src/services/: Business logic for settings building - src/middleware/: Error handling and logging middleware - src/utils/: Reusable utilities (shell commands, error helpers) - src/types/: TypeScript type definitions and custom error classes - src/tests/: Complete test coverage with unit and integration tests Key Improvements: - Added health check endpoint (GET /health) - Enhanced error handling with custom error types - Improved CI/CD with proper test job before Docker build - Better documentation (README.md and new CLAUDE.md) - Added test scripts for API and Docker testing - Security dependency overrides for vulnerabilities - Proper .gitignore for Aider chat history Testing: - All 25 tests passing across 11 test files - TypeScript type checking passes with strict mode - Linting passes with no issues - No regressions - maintains full backward compatibility Documentation: - Enhanced README with project structure and comprehensive testing instructions - Added CLAUDE.md for AI assistant context and development guidelines - Updated package.json with new test commands and build script
1 parent c90876f commit 0a56d42

35 files changed

+1534
-120
lines changed

.github/workflows/deploy.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,33 @@ on:
66
- 'main'
77

88
jobs:
9+
test:
10+
name: Test
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v4
15+
16+
- name: Setup Bun
17+
uses: oven-sh/setup-bun@v1
18+
with:
19+
bun-version: latest
20+
21+
- name: Install dependencies
22+
run: bun install
23+
24+
- name: Run TypeScript type checking
25+
run: bun tsc --noEmit
26+
27+
- name: Run tests
28+
run: bun test
29+
30+
- name: Run linting
31+
run: bun run lint
32+
933
docker:
1034
runs-on: ubuntu-latest
35+
needs: test
1136
steps:
1237
- name: Checkout
1338
uses: actions/checkout@v4

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,6 @@ dist
173173

174174
# Finder (MacOS) folder config
175175
.DS_Store
176+
177+
# Aider chat history
178+
.aider.chat.history.md

CLAUDE.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is a REST API that processes CoMapeo configuration files. It accepts ZIP files containing CoMapeo configuration settings, processes them using the `mapeo-settings-builder` CLI tool, and returns `.comapeocat` files ready for use in CoMapeo applications.
8+
9+
**Runtime**: Bun (JavaScript runtime, pinned to v1.0.16)
10+
**Framework**: Elysia (Bun-native web framework)
11+
**Key Dependency**: `mapeo-settings-builder` (must be installed globally)
12+
13+
## Development Commands
14+
15+
```bash
16+
# Install dependencies
17+
bun install
18+
19+
# Development mode with hot reload
20+
bun run dev
21+
22+
# Production mode
23+
bun run start
24+
25+
# Build for deployment
26+
bun run build
27+
28+
# Linting
29+
bun run lint
30+
31+
# Run all tests
32+
bun test
33+
34+
# Run specific test suites
35+
bun run test:unit
36+
bun run test:integration
37+
38+
# Run a single test file
39+
bun test src/tests/unit/utils/shell.test.ts
40+
41+
# Test the API with a real ZIP file (requires running server)
42+
./scripts/test-api.sh
43+
./scripts/test-api.sh --url http://localhost:3000 --file path/to/config.zip --output response.comapeocat
44+
```
45+
46+
## Architecture
47+
48+
### Request Flow
49+
50+
1. **API Entry** (`src/app.ts`): Elysia app with single POST endpoint at `/`
51+
2. **Controller** (`src/controllers/settingsController.ts`): Handles file upload, converts File to ArrayBuffer
52+
3. **Service** (`src/services/settingsBuilder.ts`): Core processing logic
53+
- Creates temporary directory with `fs.mkdtemp()`
54+
- Extracts ZIP using `adm-zip`
55+
- Reads `metadata.json` to determine output filename
56+
- Spawns `mapeo-settings-builder build` command via `runShellCommand()`
57+
- Polls for output file (max 120 attempts, 1s intervals)
58+
- Returns path to built `.comapeocat` file
59+
4. **Response**: `Bun.file()` streams the built file back to client
60+
61+
### Key Patterns
62+
63+
**Async Build Process**: The `mapeo-settings-builder` command runs asynchronously. The service polls the build directory waiting for the `.comapeocat` file to appear rather than blocking on command completion.
64+
65+
**Temporary Directory Management**: Each request creates a unique temp directory using `os.tmpdir()` with prefix `comapeo-settings-`. Cleanup is currently commented out in `settingsBuilder.ts:58` but should be enabled for production.
66+
67+
**Error Handling**: Controller catches errors and returns 500 responses with error messages. No custom error types or middleware are currently in use.
68+
69+
### File Structure
70+
71+
```
72+
src/
73+
├── app.ts # Elysia app factory
74+
├── index.ts # Entry point, starts server
75+
├── config/app.ts # Configuration constants (port, timeouts, etc.)
76+
├── controllers/
77+
│ ├── settingsController.ts # File upload handler
78+
│ └── healthController.ts # Health check endpoint
79+
├── services/
80+
│ └── settingsBuilder.ts # Core build logic
81+
├── utils/
82+
│ ├── shell.ts # Shell command execution helpers
83+
│ └── errorHelpers.ts # Error utilities
84+
├── middleware/
85+
│ ├── logger.ts # Request logging
86+
│ └── errorHandler.ts # Error handling middleware
87+
└── tests/
88+
├── unit/ # Unit tests for all modules
89+
└── integration/ # Integration tests with test server
90+
```
91+
92+
## Docker
93+
94+
The project uses a multi-stage Docker setup:
95+
96+
- Base image: `node:18-bullseye-slim` (not official Bun image due to `mapnik` native dependencies)
97+
- Installs Bun v1.0.16 globally
98+
- Installs `mapeo-settings-builder` globally
99+
- Exposes port 3000
100+
- Entry point: `bun run index.ts`
101+
102+
**Build and run locally**:
103+
```bash
104+
docker build -t comapeo-config-builder-api:local .
105+
docker run -p 3000:3000 comapeo-config-builder-api:local
106+
```
107+
108+
## Testing Strategy
109+
110+
- **Unit tests**: Mock external dependencies (shell commands, file system)
111+
- **Integration tests**: Use `test-server.ts` to spin up real Elysia instance
112+
- **Test environment**: Set via `BUN_ENV=test` in package.json scripts
113+
- **Test helpers**: Shared utilities in `src/tests/utils/testHelpers.ts`
114+
115+
## CI/CD
116+
117+
GitHub Actions workflows in `.github/workflows/`:
118+
119+
- **deploy.yml**: Builds Docker image, runs tests, deploys to GitHub Container Registry
120+
- **docker-test.yml**: Tests the Docker image with real API requests
121+
- **fly-deploy.yml**: Legacy Fly.io deployment (may be deprecated)
122+
123+
## API Usage
124+
125+
```bash
126+
# Upload a ZIP file and receive a .comapeocat file
127+
curl -X POST \
128+
-H "Content-Type: multipart/form-data" \
129+
-F "file=@config.zip" \
130+
--output output.comapeocat \
131+
http://localhost:3000/
132+
```
133+
134+
## Important Notes
135+
136+
- The `mapeo-settings-builder` CLI must be installed globally in the execution environment
137+
- Input ZIP must contain a `metadata.json` file with `name` and `version` fields
138+
- Build process is asynchronous and uses polling with configurable timeout (default: 120s)
139+
- CORS is enabled via `@elysiajs/cors`
140+
- TypeScript is configured for strict mode with ESNext target

README.md

Lines changed: 112 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,49 @@
1-
# comapeo-config-builder-api
1+
# Comapeo Config Builder API
22

33
This project provides an API for building CoMapeo configuration settings using the `mapeo-settings-builder` tool. It accepts a ZIP file containing CoMapeo configuration files, processes it, and outputs a `.comapeocat` file. The API streamlines the process of converting raw configuration data into a format that can be directly used by CoMapeo applications.
44

55
Key features:
66
- Accepts a ZIP file upload containing CoMapeo configuration settings
77
- Utilizes the `mapeo-settings-builder` tool to process the configuration
88
- Outputs a built `.comapeocat` file ready for use in CoMapeo
9+
- Robust error handling and validation
10+
- Comprehensive test coverage
11+
12+
## Project Structure
13+
14+
- **src/**: Source code
15+
- **config/**: Application configuration
16+
- **controllers/**: API route handlers
17+
- **middleware/**: Express middleware functions
18+
- **services/**: Business logic
19+
- **types/**: TypeScript type definitions
20+
- **utils/**: Utility functions
21+
- **tests/**: Test files
22+
- **unit/**: Unit tests
23+
- **integration/**: Integration tests
24+
- **utils/**: Test utilities
925

1026
## Installation
1127

1228
### Using Docker
1329

14-
1. **Run the Docker container:**
30+
1. **Pull the Docker image:**
1531

1632
```bash
17-
docker run -p 3000:3000 communityfirst/comapeo-config-builder-api
33+
docker pull ghcr.io/digidem/comapeo-config-builder-api:latest
34+
```
35+
36+
2. **Run the Docker container:**
37+
38+
```bash
39+
docker run -p 3000:3000 ghcr.io/digidem/comapeo-config-builder-api:latest
40+
```
41+
42+
3. **Build and run locally:**
43+
44+
```bash
45+
docker build -t comapeo-config-builder-api:local .
46+
docker run -p 3000:3000 comapeo-config-builder-api:local
1847
```
1948

2049
### Using Bun
@@ -28,19 +57,95 @@ Key features:
2857
2. **Install `mapeo-settings-builder` globally:**
2958

3059
```bash
31-
bun install -g mapeo-settings-builder
60+
npm install -g mapeo-settings-builder
3261
```
3362

3463
3. **Run the application:**
3564

36-
```bash
37-
bun run index.ts
65+
```bash
66+
bun run dev
3867
```
3968

69+
## Development
70+
71+
### Running the API
72+
73+
```bash
74+
# Development mode with hot reload
75+
bun run dev
76+
77+
# Production mode
78+
bun run start
79+
```
80+
81+
### Testing
82+
83+
```bash
84+
# Run all tests
85+
bun test
86+
87+
# Run tests with coverage
88+
bun test --coverage
89+
90+
# Run specific test files
91+
bun test src/tests/unit/utils/shell.test.ts
92+
93+
# Test the API with a real ZIP file
94+
./scripts/test-api.sh
95+
96+
# Test the API with a custom URL and ZIP file
97+
./scripts/test-api.sh --url http://localhost:3000 --file path/to/config.zip --output response.comapeocat
98+
```
99+
100+
### Building
101+
102+
```bash
103+
# Build the project
104+
bun run build
105+
```
106+
107+
### Linting
108+
109+
```bash
110+
# Run linter
111+
bun run lint
112+
```
113+
40114
## Usage
41115

42116
Use the following `curl` command to POST a ZIP file to the API:
43117

44118
```bash
45-
curl -X POST -H "Content-Type: multipart/form-data" -F "file=@config-cultural-monitoring.zip" --output config-cultural-monitoring.comapeocat http://localhost:3000/```
119+
curl -X POST -H "Content-Type: multipart/form-data" -F "file=@config-cultural-monitoring.zip" --output config-cultural-monitoring.comapeocat http://localhost:3000/
120+
```
121+
122+
### API Endpoints
123+
124+
#### Health Check
125+
126+
```
127+
GET /health
46128
```
129+
130+
Returns the health status of the API.
131+
132+
#### Build Configuration
133+
134+
```
135+
POST /
136+
```
137+
138+
Builds a Comapeo configuration file from a ZIP file.
139+
140+
## CI/CD
141+
142+
The project uses GitHub Actions for continuous integration and deployment:
143+
144+
- **CI Workflow**: Runs tests, type checking, and health checks on every push and pull request
145+
- **Docker Build, Test, and Deploy**: Builds the Docker image, tests it with real API requests, and deploys it to GitHub Container Registry
146+
- **Security Scan**: Checks for vulnerabilities in dependencies and Docker image
147+
- **Lint**: Ensures code quality and style consistency
148+
149+
## License
150+
151+
MIT

0 commit comments

Comments
 (0)