Skip to content

jmetzler-data/CSE-practice

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CSE-practice

A Node.js REST API built as a technical practice project for a Client Success Engineer role. The project simulates a backend service for managing artist stream data, and was built progressively across 10 sections. Each shipped as its own pull request to practice real-world engineering workflows including SQLite persistence, input validation, authentication, rate limiting, search, logging, and a frontend dashboard.


Prerequisites

Make sure the following are installed before getting started:

  • Node.js (v18 or higher)
  • Git
  • Postman - for testing API endpoints
  • A terminal running Git Bash (Windows) or any Unix-style shell

Setup

git clone https://github.com/jmetzler-data/chartmetric-practice.git
cd chartmetric-practice
npm install

This installs all dependencies: express, better-sqlite3, and express-rate-limit.


Running the Server

node index.js

You should see:

Running on port 3000

The server runs at http://localhost:3000. Leave this terminal open while testing. Open a second Git Bash terminal for any additional commands.

Note: The SQLite database file (artists.db) is created automatically on first run and seeded with 3 artists. It is excluded from version control via .gitignore.


API Endpoints

All endpoints accept and return JSON. Test using Postman or any HTTP client.

GET /artists

Returns all artists sorted by stream count descending. Optionally filter by minimum streams.

GET http://localhost:3000/artists
GET http://localhost:3000/artists?minStreams=900000

Success response:

[
  { "id": 1, "name": "Kanye West", "streams": 1000000 },
  { "id": 3, "name": "Twenty One Pilots", "streams": 920000 }
]

GET /artists/:id

Returns a single artist by ID.

GET http://localhost:3000/artists/1

Success response:

{ "id": 1, "name": "Kanye West", "streams": 1000000 }

Error responses:

400 — id must be a number          (e.g. /artists/abc)
404 — Artist not found             (e.g. /artists/99)

GET /artists/search

Searches artists by name. Supports partial matches.

GET http://localhost:3000/artists/search?name=kan
GET http://localhost:3000/artists/search?name=one

Success response:

[{ "id": 1, "name": "Kanye West", "streams": 1000000 }]

Error responses:

400 - name query parameter is required    (no ?name= provided)
404 - No artists found matching '...'     (no results)

POST /artists

Adds a new artist. Requires a valid name and non-negative stream count.

POST http://localhost:3000/artists

Request body:

{ "name": "Arctic Monkeys", "streams": 780000 }

Success response:

{ "id": 4, "name": "Arctic Monkeys", "streams": 780000 }

Error responses:

400 - name is required and must be a non-empty string
400 - streams is required and must be a non-negative number

PUT /artists/:id

Updates an existing artist's name, streams, or both. Any field not provided keeps its current value.

PUT http://localhost:3000/artists/2

Request body (partial update is fine):

{ "streams": 999999 }

Success response:

{ "id": 2, "name": "Twenty One Pilots", "streams": 999999 }

Error responses:

400 - id must be a number
400 - name must be a non-empty string
400 - streams must be a non-negative number
404 - Artist not found

DELETE /artists/:id

Removes an artist by ID.

DELETE http://localhost:3000/artists/1

Success response:

{ "message": "Artist 1 deleted" }

Error responses:

400 - id must be a number
404 - Artist not found

Features

Rate Limiting

All endpoints are rate limited to 5 requests per minute per IP. Exceeding this returns:

{ "error": "Too many requests - please wait before trying again" }

HTTP status: 429 Too Many Requests


API Key Authentication

API key auth is implemented but commented out by default to allow the HTML dashboard to function without headers. To enable it, uncomment the auth middleware block in index.js and include the following header in all Postman requests:

Key:   x-api-key
Value: secret123

Requests without a valid key return:

{ "error": "Unauthorized - missing or invalid API key" }

HTTP status: 401 Unauthorized


HTML Dashboard

A browser-based dashboard displays all artists in a styled table, fetched live from the API.

http://localhost:3000

Requires the API key middleware to remain commented out, as browsers cannot send custom headers on page load.


Request & Error Logging

All significant events are written to logs.txt in the project root with timestamps and log levels (INFO, WARN, ERROR). The file is created automatically on first write.

To view logs:

cat logs.txt

Example output:

[2026-06-08T14:22:01.000Z] [INFO] GET /artists returned 3 artist(s) with minStreams=0
[2026-06-08T14:22:10.000Z] [WARN] Artist not found: id=99
[2026-06-08T14:22:18.000Z] [INFO] New artist created: 'Radiohead' (id=4, streams=670000)
[2026-06-08T14:22:25.000Z] [INFO] Artist deleted: 'Kanye West' (id=1)

logs.txt and artists.db are excluded from version control via .gitignore.


Data Discrepancy Script

A standalone script that compares two datasets and flags mismatches — simulating a real-world investigation when a client reports incorrect data.

node discrepancy.js

Example output:

===== Data Discrepancy Report =====
[MISMATCH] ID 2 'Twenty One Pilots'
           Internal: 920,000
           External: 875,000
           Diff:     -45,000
[MISSING]  ID 4 'Arctic Monkeys' exists externally but not internally
===================================

Project Structure

chartmetric-practice/
├── index.js          # Main Express server - all routes, middleware, and database logic
├── discrepancy.js    # Standalone data comparison script
├── dashboard.html    # Browser-based artist stream dashboard
├── package.json      # Project config and dependencies
├── .gitignore        # Excludes artists.db and logs.txt
└── README.md

Dependencies

Package Purpose
express HTTP server and routing
better-sqlite3 SQLite database (synchronous Node.js driver)
express-rate-limit Per-IP request rate limiting

What This Project Demonstrates

  • REST API design with full CRUD operations
  • SQLite database integration with seeding and persistence
  • Input validation and descriptive error responses
  • API key authentication middleware
  • Rate limiting
  • Name-based search with partial matching
  • Timestamped file-based logging across all routes
  • Frontend-to-backend integration via fetch
  • Data discrepancy detection scripting
  • Git feature branch workflow with pull requests throughout

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors