Skip to content

About

E-commerce REST API (e-ticaret API) for online stores: products, cart, checkout and orders with JWT auth, Turkish KDV/VAT pricing, idempotent and oversell-proof checkout. Zero-dependency Node.js, TypeScript and SQLite backend.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

6 Commits

Folders and files

Repository files navigation

E-commerce REST API

CI Node TypeScript SQLite Dependencies License: MIT

A complete e-commerce backend (REST API) for a small online store: catalog, cart, checkout and order management, built with zero runtime dependencies on Node.js 22+ (node:http, node:sqlite, node:crypto).

It focuses on the parts that usually go wrong in real shops:

  • No overselling. Checkout runs in one SQLite transaction and decrements stock with a guarded UPDATE … WHERE stock >= ?. Two customers racing for the last item: one gets the order, the other a 409.
  • Safe retries. POST /orders accepts an Idempotency-Key header. A double-clicked "Pay" button creates one order.
  • Correct money. Prices are integer kuruş, VAT-inclusive, with per-product Turkish VAT (KDV) rates of 0, 1, 10 or 20 %.
  • Order workflow. pending → paid → shipped → delivered, or cancelled, which puts the stock back.
  • Secure auth. scrypt password hashes, HS256 JWTs verified in constant time, no user enumeration on login.

Quick start

git clone https://github.com/bahriy-dev/ecommerce-rest-api.git
cd ecommerce-rest-api
npm start      # http://localhost:3000/api/v1 (seeds an admin and 3 demo products)
npm test       # 27 tests: unit + full HTTP flows

With Docker:

docker build -t ecommerce-api .
docker run -p 3000:3000 -e JWT_SECRET=change-me -v shop-data:/data ecommerce-api

API

All routes are under /api/v1. Send Authorization: Bearer <token> for protected routes.

Method Path Auth Description
POST /auth/register — Create a customer account, returns a JWT
POST /auth/login — Log in, returns a JWT
GET /me user Current user
GET /categories — Categories
GET /products — Search, filter and paginate (see below)
GET /products/:id — Product detail
POST /products admin Create a product
PATCH /products/:id admin Update any field
DELETE /products/:id admin Soft delete (keeps order history intact)
GET /cart user Cart lines, availability and totals
PUT /cart/items/:productId user Set quantity (0 removes)
DELETE /cart user Empty the cart
POST /orders user Checkout. Supports Idempotency-Key
GET /orders user My orders (?all=true for admins)
GET /orders/:id user Order detail (owner or admin)
POST /orders/:id/cancel user Cancel a pending order
PATCH /orders/:id/status admin Move an order through the workflow

Product query parameters: q, category (slug), minPrice, maxPrice (kuruş), inStock=true, sort (newest, price_asc, price_desc, name), page, limit (max 100).

Example: checkout

TOKEN=$(curl -s localhost:3000/api/v1/auth/register -H 'Content-Type: application/json' \
  -d '{"email":"ayse@example.com","name":"Ayşe","password":"password123"}' | jq -r .token)

curl -X PUT localhost:3000/api/v1/cart/items/1 -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' -d '{"quantity":2}'

curl -X POST localhost:3000/api/v1/orders -H "Authorization: Bearer $TOKEN" \
  -H 'Idempotency-Key: 6f1c…' -H 'Content-Type: application/json' \
  -d '{"shippingAddress":"Caferağa Mah. Moda Cad. No:1, Kadıköy, İstanbul 34710"}'
{
  "id": 1,
  "status": "pending",
  "subtotal": 499800,
  "vatTotal": 83300,
  "shipping": 0,
  "total": 499800,
  "items": [{ "productId": 1, "name": "Mekanik Klavye", "unitPrice": 249900, "vatRate": 20, "quantity": 2 }]
}

Errors always look like { "error": "…", "details": { … } }. Validation errors return 422 with one message per field.

Configuration

Variable Default Description
PORT 3000 HTTP port
DATABASE_PATH data.db SQLite file (:memory: for throwaway runs)
JWT_SECRET dev value Required in production
ADMIN_EMAIL / ADMIN_PASSWORD admin@example.com / admin12345 First admin, created once
SHIPPING_FEE 4990 Flat shipping fee in kuruş
FREE_SHIPPING_OVER 50000 Free shipping threshold in kuruş
CORS_ORIGIN * Allowed origin
LOG_REQUESTS — 1 logs method, path, status and duration

Project layout

src/
  http.ts        router, JSON body parsing, errors
  auth.ts        scrypt passwords, JWT, role guards
  validate.ts    tiny schema validator (422 with per-field errors)
  db.ts          schema migrations (PRAGMA user_version), transactions, seed data
  pricing.ts     VAT, shipping and totals in integer kuruş
  routes/        auth, catalog, cart, orders
  app.ts         wiring, CORS, error handling
test/            node:test unit tests and end-to-end HTTP tests

License

MIT © Bahri YILMAZ

About

E-commerce REST API (e-ticaret API) for online stores: products, cart, checkout and orders with JWT auth, Turkish KDV/VAT pricing, idempotent and oversell-proof checkout. Zero-dependency Node.js, TypeScript and SQLite backend.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages