User Management API with CRUD Operations

mediumTypeScript

Lesson

Building CRUD APIs with In-Memory Storage

CRUD operations (Create, Read, Update, Delete) form the backbone of most web applications. When building APIs, these operations typically map to HTTP methods: POST for creating, GET for reading, PUT for updating, and DELETE for removing resources.

In-Memory Storage Pattern

Before connecting to databases, it's common to prototype APIs using in-memory storage. This approach uses simple data structures like arrays or objects to store data temporarily. While data doesn't persist between server restarts, in-memory storage is perfect for development, testing, and learning core API patterns.

Validation and Error Handling

Robust APIs validate input data and provide clear error messages. Validation should check for required fields, data types, and format constraints. For user management, this typically means ensuring names aren't empty and emails follow a basic format.

API Response Consistency

Well-designed APIs return consistent response structures. A common pattern is to use objects with success boolean flags, optional data for successful responses, and error messages for failures. This consistency makes APIs easier to consume and debug.

Separation of Concerns

Good API architecture separates data storage logic from HTTP handling logic. A storage layer (like UserStore) manages data operations, while an API layer (like UserAPI) handles HTTP concerns like validation and response formatting. This separation makes code more testable and maintainable.

Example
1// Storage layer - handles data operations 2class ProductStore { 3 private products: Product[] = []; 4 private nextId = 1; 5 6 create(name: string, price: number): Product { 7 const product = { id: this.nextId++, name, price }; 8 this.products.push(product); 9 return product; 10 } 11 12 findAll(): Product[] { 13 return [...this.products]; // Return a copy 14 } 15} 16 17// API layer - handles HTTP concerns 18class ProductAPI { 19 constructor(private store: ProductStore) {} 20 21 createProduct(data: any): APIResponse { 22 // Validation first 23 if (!data.name || typeof data.price !== 'number') { 24 return { success: false, error: 'Invalid product data' }; 25 } 26 27 // Then delegate to storage 28 const product = this.store.create(data.name, data.price); 29 return { success: true, data: product }; 30 } 31}
L7Always return copies of stored data to prevent external modification
L15Validate input before calling storage methods
L21Consistent response format with success flag and optional data/error

Key Takeaways

  • •In-memory storage using arrays and auto-incrementing IDs is perfect for prototyping APIs
  • •Separate storage logic from API logic to improve testability and maintainability
  • •Consistent response formats with success flags make APIs easier to consume and debug
Loading...