Skip to content

chetanbatra25/nextjs-token-api-manager

Repository files navigation

Token Manager - Next.js (App Router) Mini Project

A production-ready, well-structured TypeScript service built with Next.js that exposes a typed API for managing user access tokens. The implementation features a modular architecture, comprehensive testing, and a polished frontend interface.

Stack

  • Next.js 16 (App Router) - React framework with API routes
  • TypeScript 5 - Full type safety across the codebase
  • SQLite (better-sqlite3) - Lightweight database for token storage
  • Jest - Unit testing framework
  • Tailwind CSS - Minimal styling for the frontend

Prerequisites

  • Node.js 20+ (or use Docker)
  • npm or yarn

How to Run

Local Development

  1. Install dependencies:

    npm install
  2. Run the development server:

    npm run dev
  3. Access the application:

  4. Run tests:

    npm test

Docker

  1. Build the image:

    docker build -t token-api .
  2. Run the container:

    docker run -p 3000:3000 -e API_KEY=your-secret-key token-api

Production Build

npm run build
npm start

API Endpoints

POST /api/tokens

Creates a new token for a user.

Request Headers:

  • X-API-KEY: API key for authentication (default: dev-secret in development)

Request Body (JSON):

{
  "userId": "123",
  "scopes": ["read", "write"],
  "expiresInMinutes": 60
}

Validation:

  • userId must be a non-empty string
  • scopes must be a non-empty array of strings
  • expiresInMinutes must be a positive integer

Response (201 Created):

{
  "id": "token_abc123",
  "userId": "123",
  "scopes": ["read", "write"],
  "createdAt": "2025-01-01T10:00:00.000Z",
  "expiresAt": "2025-01-01T11:00:00.000Z",
  "token": "9f0c2d6a3b..."
}

Error Responses:

  • 400 Bad Request - Invalid input validation
  • 401 Unauthorized - Missing or invalid API key
  • 500 Internal Server Error - Server error

GET /api/tokens?userId=123

Lists all non-expired tokens for a specific user.

Request Headers:

  • X-API-KEY: API key for authentication

Query Parameters:

  • userId (required) - The user ID to query tokens for

Response (200 OK):

[
  {
    "id": "token_abc123",
    "userId": "123",
    "scopes": ["read", "write"],
    "createdAt": "2025-01-01T10:00:00.000Z",
    "expiresAt": "2025-01-01T11:00:00.000Z",
    "token": "9f0c2d6a3b..."
  }
]

Empty Response (200 OK): If no active tokens are found for the user, an empty array is returned:

[]

Error Responses:

  • 400 Bad Request - Missing userId parameter or invalid userId
  • 401 Unauthorized - Missing or invalid API key
  • 500 Internal Server Error - Server error

Project Structure

The project follows a module-based architecture where each API endpoint is self-contained with its own types, validation, service layer, and responses. This makes it easy to add new endpoints and maintain the codebase.

src/
├── app/
│   ├── api/
│   │   └── tokens/                    # Tokens API Module (self-contained)
│   │       ├── route.ts                # API route handlers (GET/POST)
│   │       ├── service.ts              # Database operations & business logic
│   │       ├── validation.ts           # Input validation functions
│   │       ├── responses.ts            # Module-specific response helpers
│   │       └── types.ts                # Token-specific type definitions
│   ├── page.tsx                        # Frontend UI (two-section layout)
│   ├── layout.tsx                      # Root layout
│   └── globals.css                     # Global styles
├── lib/
│   ├── api/
│   │   └── shared/                     # Shared API utilities
│   │       ├── middleware.ts           # Authentication middleware
│   │       └── responses.ts            # Generic response helpers
│   ├── auth.ts                         # Authentication utilities
│   ├── dbConnection.ts                 # Database connection management
│   ├── migrate.ts                      # Database schema migrations
│   ├── tokenUtils.ts                   # Pure utility functions
│   └── types.ts                        # Shared type definitions
└── types/
    └── better-sqlite3.d.ts             # Type definitions

__tests__/
├── setup.ts                            # Test setup & configuration
├── tokenUtils.test.ts                  # Token utility tests (comprehensive)
├── db.test.ts                          # Service/database integration tests
├── validation.test.ts                  # Input validation tests
└── middleware.test.ts                  # Authentication middleware tests

Architecture Highlights

  • Module-Based Design: Each API endpoint (/api/tokens) is a complete module with all related code
  • Separation of Concerns: Clear boundaries between routes, validation, service, and types
  • Shared Utilities: Common functionality (auth, responses) in lib/api/shared/
  • Type Safety: Full TypeScript coverage with explicit types throughout
  • Scalable: Easy to add new endpoints by following the same module pattern

Code Design Principles

  • Type Safety: All modules use explicit TypeScript types and interfaces. No any types in core logic.
  • Module Organization: Each API endpoint is self-contained with its own types, validation, service, and responses
  • Separation of Concerns:
    • API routes handle HTTP concerns (validation, status codes)
    • Service layer handles business logic and database operations
    • Validation layer handles input validation
    • Utility functions are pure and testable
  • Input Validation: Comprehensive validation with clear, user-friendly error messages
  • Error Handling: Appropriate HTTP status codes and consistent error response format
  • Empty Response Handling: APIs always return consistent structures (empty arrays for lists)
  • Testability: Core logic is separated into pure functions with comprehensive unit and integration tests
  • Shared Middleware: Authentication and common logic shared across all endpoints

Assumptions & Simplifications

  1. Authentication: Simple header-based API key authentication (X-API-KEY). Default key is dev-secret when API_KEY environment variable is not set. In production, set API_KEY environment variable.

  2. Database: SQLite database stored at .data/tokens.db in the project root. The database directory is created automatically on first run.

  3. Token Generation: Tokens are generated using cryptographically secure random bytes (24 bytes hex-encoded). Token IDs use the format token_<hex>.

  4. Expiry Handling: Expired tokens are filtered out at query time. No automatic cleanup job is implemented.

  5. Frontend: Modern, responsive UI with two distinct sections:

    • Create Token Section: Form to generate new tokens with validation
    • List Tokens Section: Search and display tokens with empty state handling
    • Features: Success/error messages, loading states, form validation, auto-refresh
  6. Error Messages: Error messages are user-friendly but don't expose internal implementation details.

  7. Database Migrations: Schema is created automatically on first run. No versioned migration system for this minimal implementation.

Testing

Comprehensive test suite with 50+ test cases covering:

Test Files

  1. tokenUtils.test.ts - Token utility functions

    • ID generation (uniqueness, format)
    • Token string generation (length, format)
    • Expiry calculations (edge cases, defaults)
    • Expiry detection (boundary conditions)
  2. db.test.ts - Service layer & database operations

    • Token creation and persistence
    • Token listing with filtering
    • Expiry filtering
    • User filtering
    • Empty response handling
    • Multiple tokens per user
    • Ordering and sorting
  3. validation.test.ts - Input validation

    • POST request validation (20+ test cases)
    • GET query parameter validation
    • Missing fields, invalid types, edge cases
    • Valid input acceptance
  4. middleware.test.ts - Authentication middleware

    • Valid API key handling
    • Invalid API key handling
    • Missing API key handling

Running Tests

# Run all tests
npm test

# Run with coverage report
npm test -- --coverage

# Run specific test file
npm test -- validation.test.ts

# Run in watch mode
npm test -- --watch

Test Coverage

  • Token Utils: ~100% coverage
  • Validation: ~100% coverage
  • Service/DB: High coverage with integration tests
  • Middleware: High coverage with mocked dependencies

All tests are isolated, use fresh database instances, and include proper cleanup.

Environment Variables

  • API_KEY - API key for authentication (defaults to dev-secret in development)
  • NODE_ENV - Set to production for production builds
  • PORT - Server port (defaults to 3000)

Frontend Features

The frontend provides a modern, user-friendly interface with:

  • Two-Section Layout:

    • Create Token: Form with validation for generating new tokens
    • List Tokens: Search interface for viewing user tokens
  • User Experience:

    • Real-time validation feedback
    • Success/error message display
    • Loading states with spinners
    • Empty state handling with helpful messages
    • Auto-refresh after token creation
    • Responsive design (mobile-friendly)
  • Styling:

    • Modern gradient backgrounds
    • Card-based layout with shadows
    • Color-coded messages (green for success, red for errors)
    • Token cards with badges for scopes
    • Expiry date color coding

API Design Patterns

Module Structure

Each API module follows this pattern:

app/api/{module}/
├── route.ts      # HTTP handlers (GET, POST, etc.)
├── service.ts    # Business logic & database operations
├── validation.ts # Input validation
├── responses.ts  # Response helpers
└── types.ts      # Type definitions

Shared Utilities

Common functionality in lib/api/shared/:

  • middleware.ts: Authentication middleware (withAuth())
  • responses.ts: Generic response helpers (error, success, etc.)

Benefits

  • Easy to Extend: Add new endpoints by creating new modules
  • Consistent: All endpoints follow the same structure
  • Maintainable: Related code is co-located
  • Testable: Each module can be tested independently

Future Enhancements

Potential improvements for a production system:

  • Token revocation endpoint (DELETE /api/tokens/:id)
  • Automatic cleanup of expired tokens (scheduled job)
  • Rate limiting per API key
  • More robust authentication (JWT, OAuth)
  • Database connection pooling
  • API documentation (OpenAPI/Swagger)
  • Logging and monitoring (structured logging)
  • Environment-specific configuration management
  • Token refresh mechanism
  • Audit logging for token operations

About

Code sample for Next.JS API Token Manager

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors