Skip to content

diegodevtech/API-tickets_app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 

Repository files navigation

Tickets API

Node JavaScript HTTP Storage License

A lightweight, framework-free backend API to manage support tickets, built with raw Node.js HTTP primitives.

This project demonstrates:

  • Route parsing with dynamic params (:id) and query strings.
  • JSON request body parsing middleware.
  • File-based persistence (db.json) through a custom database layer.
  • Ticket lifecycle operations (open -> closed -> delete).
  • Business rule enforcement: only closed tickets can be deleted.

Table of Contents

  1. Why This Project
  2. What It Does
  3. System Architecture
  4. Ticket Lifecycle
  5. Project Structure
  6. Data Model
  7. Business Rules
  8. API Reference
  9. Run Locally
  10. Developer Notes
  11. Roadmap Ideas

Why This Project

This API is an excellent baseline for understanding backend fundamentals without hiding complexity behind frameworks.

It is intentionally simple, but still covers real backend concerns:

  • Routing and controller orchestration.
  • Request parsing and response formatting.
  • Persistence and data mutation.
  • Filtering and search via query parameters.
  • Domain constraints and error handling.

What It Does

The API manages technical support tickets with these capabilities:

  • Create a ticket with equipment, issue description, and requester name.
  • List tickets.
  • Filter tickets by status using query params (?status=open or ?status=closed).
  • Update ticket details.
  • Close a ticket and register its solution.
  • Delete a ticket only when status is closed.

System Architecture

flowchart LR
  Client[HTTP Client\nInsomnia / Postman / cURL / Frontend] --> Server[Node HTTP Server\nsrc/server.js]
  Server --> JSON[jsonHandler middleware\nparse request body]
  JSON --> Router[routehandler middleware\nmatch method + path]
  Router --> Controllers[Tickets Controllers\ncreate/index/update/updateStatus/remove]
  Controllers --> DB[Database class\nsrc/database/database.js]
  DB --> File[(db.json)]
Loading

Request Flow

sequenceDiagram
  autonumber
  participant C as Client
  participant S as server.js
  participant J as jsonHandler
  participant R as routeHandler
  participant T as Ticket Controller
  participant D as Database
  participant F as db.json

  C->>S: HTTP request
  S->>J: Parse body + set Content-Type JSON
  J->>R: Continue pipeline
  R->>R: Match method + regex path
  alt Route found
    R->>T: controller({ request, response, database })
    T->>D: select/insert/update/remove
    D->>F: read/write persisted state
    T-->>C: HTTP response
  else Route not found
    R-->>C: 404
  end
Loading

Ticket Lifecycle

stateDiagram-v2
  [*] --> Open: POST /tickets
  Open --> Open: PUT /tickets/:id
  Open --> Closed: PATCH /tickets/:id/close
  Closed --> Closed: PUT /tickets/:id
  Closed --> Deleted: DELETE /tickets/:id
  Open --> Open: DELETE /tickets/:id\n(Rejected: only closed can be deleted)
Loading

Project Structure

.
|-- package.json
|-- README.md
`-- src
    |-- server.js
    |-- controllers
    |   `-- tickets
    |       |-- create.js
    |       |-- index.js
    |       |-- remove.js
    |       |-- update.js
    |       `-- updateStatus.js
    |-- database
    |   |-- database.js
    |   `-- db.json
    |-- middleware
    |   |-- jsonHandler.js
    |   `-- routeHandler.js
    |-- routes
    |   |-- index.js
    |   `-- tickets.js
    `-- utils
        |-- extractQueryParams.js
        `-- parseRoutePath.js

Data Model

A ticket stored in db.json follows this shape:

{
  "id": "uuid",
  "equipment": "Keyboard",
  "description": "ALT key is stuck",
  "user_name": "Diego Cunha",
  "status": "open",
  "created_at": "2026-03-26T20:49:57.161Z",
  "updated_at": "2026-03-26T20:49:57.161Z",
  "solution": "optional, present when closed"
}
Field Type Required on create Notes
id string Auto Generated with randomUUID()
equipment string Yes Updated via PUT /tickets/:id
description string Yes Updated via PUT /tickets/:id
user_name string Yes Set on create
status string Auto open on create, closed on close
solution string No Added when closing ticket
created_at date string Auto Creation timestamp
updated_at date string Auto Updated on write operations

Business Rules

  1. New tickets are always created with status open.
  2. Closing a ticket (PATCH /tickets/:id/close) sets status to closed and records solution.
  3. Deleting a ticket is only allowed when its status is closed.
  4. Attempting to delete an open ticket returns 400 with:
{ "error": "Only closed tickets can be deleted." }

API Reference

Base URL: http://localhost:3333

Endpoints Summary

Method Route Description
GET /tickets List all tickets
GET /tickets?status=open List filtered tickets
POST /tickets Create a ticket
PUT /tickets/:id Update ticket equipment/description
PATCH /tickets/:id/close Close ticket with a solution
DELETE /tickets/:id Delete ticket (only if closed)

1) Create Ticket

POST /tickets

Request body:

{
  "equipment": "Notebook",
  "description": "Battery drains quickly",
  "user_name": "Alice"
}

Example:

curl -X POST http://localhost:3333/tickets \
  -H "Content-Type: application/json" \
  -d '{
    "equipment": "Notebook",
    "description": "Battery drains quickly",
    "user_name": "Alice"
  }'

Response: 201 Created

{
  "id": "f6f9964d-2adb-4a52-b4f8-b96e8f46f67b",
  "equipment": "Notebook",
  "description": "Battery drains quickly",
  "user_name": "Alice",
  "status": "open",
  "created_at": "2026-03-26T22:00:00.000Z",
  "updated_at": "2026-03-26T22:00:00.000Z"
}

2) List Tickets

GET /tickets

curl http://localhost:3333/tickets

Response: 200 OK

[
  {
    "id": "907a16df-9dd2-479c-860a-98ab33c5da9e",
    "equipment": "Keyboard",
    "description": "ALT key is stucked",
    "user_name": "Diego Cunha",
    "status": "open",
    "created_at": "2026-03-26T20:49:57.161Z",
    "updated_at": "2026-03-26T20:49:57.161Z"
  }
]

3) Filter Tickets by Status

GET /tickets?status=open

curl "http://localhost:3333/tickets?status=open"

Notes:

  • Filtering compares lowercase ticket status to the query value.
  • Use lowercase values (open, closed) for reliable matches.

4) Update Ticket

PUT /tickets/:id

Request body:

{
  "equipment": "Mechanical Keyboard",
  "description": "Left ALT key remains pressed"
}
curl -X PUT http://localhost:3333/tickets/<ticket_id> \
  -H "Content-Type: application/json" \
  -d '{
    "equipment": "Mechanical Keyboard",
    "description": "Left ALT key remains pressed"
  }'

Response: 200 OK with empty body.

5) Close Ticket

PATCH /tickets/:id/close

Request body:

{
  "solution": "Keycap and switch replaced"
}
curl -X PATCH http://localhost:3333/tickets/<ticket_id>/close \
  -H "Content-Type: application/json" \
  -d '{
    "solution": "Keycap and switch replaced"
  }'

Response: 200 OK with empty body.

6) Delete Ticket

DELETE /tickets/:id

curl -X DELETE http://localhost:3333/tickets/<ticket_id>

Success response: 200 OK

"Ticket removed successfully"

If ticket is open: 400 Bad Request

{ "error": "Only closed tickets can be deleted." }

Run Locally

Prerequisites

  • Node.js 22+ (or a modern Node.js version supporting ESM and --watch)

Setup

npm install

Start in Dev Mode

npm run dev

The server starts on:

  • http://localhost:3333

Developer Notes

Technical Highlights

  • Native Node.js HTTP server (node:http) without Express.
  • Custom route parser transforms paths into regular expressions.
  • Controller injection style: each controller receives { request, response, database }.
  • In-memory object synchronized to JSON file for persistence.

Current Behavior Worth Knowing

  1. There is no explicit payload validation yet (missing fields are not rejected).
  2. Some update/delete operations on non-existent IDs return 200 with empty/success response.
  3. Query parser expects simple key=value&key2=value2 format.
  4. Content-Type is always set to application/json.

Roadmap Ideas

  1. Add schema validation for all request bodies.
  2. Return 404 for unknown IDs in update/close/delete operations.
  3. Normalize and validate query parameters.
  4. Add pagination and sorting on list endpoint.
  5. Add automated tests (unit + integration).
  6. Add Docker support and environment-based config.
  7. Introduce logging and request correlation IDs.
  8. Add authentication and role-based authorization.

License

ISC

About

A lightweight, framework-free backend API to manage support tickets, built with raw Node.js HTTP primitives.

Topics

Resources

Stars

Watchers

Forks

Contributors