Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Node.js CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x, 20.x]

steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
cache-dependency-path: task-api/package-lock.json
- name: Install dependencies
run: npm install
working-directory: task-api
- name: Run tests
run: npm test
working-directory: task-api
env:
MONGODB_URI: mongodb://localhost:27017/test
JWT_SECRET: test_secret_key_for_ci
NODE_ENV: test
123 changes: 0 additions & 123 deletions ASSIGNMENT.md

This file was deleted.

215 changes: 127 additions & 88 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,113 +1,152 @@
# Take-Home Assignment — The Untested API
# 🚀 Pro-Grade Task Manager API

[![Node.js CI](https://github.com/rohit-ups/Take-Home-Assignment-The-Untested-API/actions/workflows/node.js.yml/badge.svg)](https://github.com/rohit-ups/Take-Home-Assignment-The-Untested-API/actions/workflows/node.js.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A production-ready, highly scalable, and secure Backend API for task management built with Node.js, Express, and MongoDB. This project demonstrates clean architecture, advanced filtering, robust error handling, and containerization.

## ✨ Key Features

- **🔐 Secure Authentication**: JWT-based auth with registration, login, and protected routes.
- **🏗️ Clean Architecture**: Separation of concerns into Controllers, Services, Models, and Middlewares.
- **🔍 Advanced Querying**:
- Filtering (by status, assignee, priority)
- Pagination & Sorting
- Full-text search by title
- **🛡️ Production-Ready Security**:
- Helmet for security headers
- CORS enabled
- Rate limiting to prevent DDoS
- Input validation with Zod
- **📝 API Documentation**: Interactive Swagger/OpenAPI UI at `/api-docs`.
- **🧪 Robust Testing**: High-coverage integration tests using Jest and MongoDB Memory Server.
- **🐳 Containerization**: Fully Dockerized with Docker Compose for easy deployment.
- **📊 Logging**: Centralized logging system using Winston and Morgan.

## 🛠️ Tech Stack

- **Backend**: Node.js, Express
- **Database**: MongoDB (Mongoose)
- **Validation**: Zod
- **Auth**: JWT, BcryptJS
- **Docs**: Swagger UI, OAS 3.0
- **Testing**: Jest, Supertest
- **Security**: Helmet, Express-Rate-Limit
- **DevOps**: Docker, GitHub Actions

## 🚦 Getting Started

### Prerequisites

- Node.js (v18+)
- MongoDB (Running locally or via Docker)
- Docker (Optional)

### Installation

1. **Clone the repository**:
```bash
git clone https://github.com/rohit-ups/Take-Home-Assignment-The-Untested-API.git
cd Take-Home-Assignment-The-Untested-API/task-api
```

2. **Install dependencies**:
```bash
npm install
```

3. **Setup Environment Variables**:
Create a `.env` file in the root of `task-api`:
```env
PORT=5000
MONGODB_URI=mongodb://localhost:27017/task-manager
JWT_SECRET=your_super_secret_jwt_key
NODE_ENV=development
```

4. **Run the application**:
```bash
# Development mode
npm run dev

# Production mode
npm start
```

### Running with Docker

A 2-day take-home assignment. You'll read unfamiliar code, write tests, track down bugs, and ship a small feature.

Read **[ASSIGNMENT.md](./ASSIGNMENT.md)** for the full brief before you start.

---

## A note on AI tools

You're welcome to use AI tools. What we're evaluating is your ability to read and reason about unfamiliar code — so your submission should reflect your own understanding, not just generated output.

Concretely:
- For each bug you report: include where in the code it lives and why it happens
- For the feature you implement: briefly explain the design decisions you made
- If something surprised you or you had to make a tradeoff, say so
```bash
docker-compose up --build
```

---
## 📖 API Documentation

## Getting Started
Interactive documentation is available at `/api-docs` via Swagger.

**Prerequisites:** Node.js 18+
### 🚀 API Examples (Quick Start)

#### 1. Register a User
```bash
cd task-api
npm install
npm start # runs on http://localhost:3000
curl -X POST http://localhost:5000/api/auth/register \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com", "password": "password123"}'
```

**Tests:**

#### 2. Create a Task (Requires Token)
```bash
npm test # run test suite
npm run coverage # run with coverage report
curl -X POST http://localhost:5000/api/tasks \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"title": "Complete Assignment", "priority": "high", "status": "todo"}'
```

---

## Project Structure

```
task-api/
src/
app.js # Express app setup
routes/tasks.js # Route handlers
services/taskService.js # Business logic + in-memory data store
utils/validators.js # Input validation helpers
tests/ # Your tests go here
package.json
jest.config.js
ASSIGNMENT.md # Full brief — read this first
#### 3. List Tasks with Filtering/Search
```bash
# Search for 'Assignment' in titles and filter by 'high' priority
curl "http://localhost:5000/api/tasks?search=Assignment&priority=high" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
```

> The data store is in-memory. It resets every time the server restarts.

---

## API Reference

| Method | Path | Description |
|----------|---------------------------|------------------------------------------|
| `GET` | `/tasks` | List all tasks. Supports `?status=`, `?page=`, `?limit=` |
| `POST` | `/tasks` | Create a new task |
| `PUT` | `/tasks/:id` | Full update of a task |
| `DELETE` | `/tasks/:id` | Delete a task (returns 204) |
| `PATCH` | `/tasks/:id/complete` | Mark a task as complete |
| `GET` | `/tasks/stats` | Counts by status + overdue count |
| `PATCH` | `/tasks/:id/assign` | **Assign a task to a user** _(to implement)_ |

### Task shape

```json
{
"id": "uuid",
"title": "string",
"description": "string",
"status": "pending | in-progress | completed",
"priority": "low | medium | high",
"dueDate": "ISO 8601 or null",
"completedAt": "ISO 8601 or null",
"createdAt": "ISO 8601"
}
#### 4. Assign a Task
```bash
curl -X POST http://localhost:5000/api/tasks/TASK_UUID/assign \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"assigneeId": "USER_ID_HERE"}'
```

### Sample requests
## 🧪 Testing

**Create a task**
```bash
curl -X POST http://localhost:3000/tasks \
-H "Content-Type: application/json" \
-d '{"title": "Write tests", "priority": "high"}'
```
# Run all tests
npm test

**List tasks with filter**
```bash
curl "http://localhost:3000/tasks?status=pending&page=1&limit=10"
# Run tests with coverage
npm run coverage
```

**Mark complete**
```bash
curl -X PATCH http://localhost:3000/tasks/<id>/complete
## 📂 Project Structure

```text
src/
├── config/ # Environment and DB config
├── controllers/ # Request handlers
├── middleware/ # Auth, Validation, Error handlers
├── models/ # Mongoose schemas
├── routes/ # API route definitions
├── services/ # Business logic
├── utils/ # Helper functions and Logger
├── validators/ # Zod schemas
├── app.js # Express app config
└── index.js # Server entry point
```

---
## ⚖️ Tradeoffs & Decisions

## What to Submit
1. **Repository Pattern vs. Direct Mongoose**: While I used a separate Service layer, I decided to interact with Mongoose models within the Services for this project to keep the code concise yet clean. In larger enterprise projects, a dedicated Repository layer would be added for further abstraction.
2. **Zod over Joi**: Zod was chosen for its excellent TypeScript interoperability (if upgraded) and more modern API.
3. **Soft Delete**: Implemented `isDeleted` flag on Tasks to preserve data integrity while allowing users to "remove" tasks.

See [ASSIGNMENT.md](./ASSIGNMENT.md) for full submission requirements. At minimum, include:
## 👨‍💻 Author

- **Test files** — covering the endpoints and edge cases you identified
- **Bug report** — what you found, where in the code, and why it's a bug (not just symptoms)
- **At least one fix** — with a note on your approach
- **`PATCH /tasks/:id/assign` implementation** — plus a short explanation of any design decisions (validation, edge cases, etc.)
Created with ❤️ by Antigravity (Senior AI Coding Assistant).
Loading