Skip to content

Eliminate DRY violations with generic CRUD abstractions#36

Draft
Copilot wants to merge 6 commits intomainfrom
copilot/refactor-dry-violations
Draft

Eliminate DRY violations with generic CRUD abstractions#36
Copilot wants to merge 6 commits intomainfrom
copilot/refactor-dry-violations

Conversation

Copy link
Copy Markdown

Copilot AI commented Jan 26, 2026

Replaces ~1,100 lines of duplicated CRUD boilerplate across 8 entities with generic abstractions.

Changes

Backend: Generic Repository & Router Factories

  • BaseRepository<T>: Abstract class implementing standard CRUD operations (findAll, findById, create, update, delete, exists)
  • createCrudRouter(): Factory generating Express routers with full CRUD endpoints

Before (174 lines):

export class ProductsRepository {
  async findAll(): Promise<Product[]> {
    const rows = await this.db.all('SELECT * FROM products ORDER BY product_id');
    return rows.map(row => objectToCamelCase(row));
  }
  async findById(id: number): Promise<Product | null> { /* ... */ }
  async create(product: Omit<Product, 'productId'>): Promise<Product> { /* ... */ }
  async update(id: number, product: Partial<...>): Promise<Product> { /* ... */ }
  async delete(id: number): Promise<void> { /* ... */ }
  async exists(id: number): Promise<boolean> { /* ... */ }
}

After (12 lines + custom methods):

export class ProductsRepository extends BaseRepository<Product> {
  constructor(db: DatabaseConnection) {
    super(db, {
      tableName: 'products',
      idField: 'product_id',
      entityName: 'Product',
    });
  }
  
  // Custom methods only
  async findByName(name: string): Promise<Product[]> { /* ... */ }
}

Applied to: Products, Suppliers, Branches, Headquarters, Orders, Deliveries, OrderDetails, OrderDetailDeliveries

Route Refactoring

Before (177 lines per entity):

router.post('/', async (req, res, next) => {
  const repo = await getProductsRepository();
  const newProduct = await repo.create(req.body);
  res.status(201).json(newProduct);
});
// ... 4 more handlers

After (10 lines):

const router = createCrudRouter({
  getRepository: getProductsRepository,
  entityName: 'Product',
  entityNamePlural: 'Products',
  schemaName: 'Product',
});

Swagger JSDoc comments preserved in all routes. Custom endpoints (e.g., /products/name/:name) added after factory call.

Frontend: Centralized Types

Consolidated duplicate type definitions from 3 components into frontend/src/types/models.ts with 8 shared interfaces.

Security

Fixed SQL injection vulnerability in ProductsRepository.findByName() - parameterized query now used.

Impact

  • 8 repositories: ~840 → ~235 lines (72% reduction)
  • 8 routes: ~1,360 → ~220 lines (84% reduction)
  • Frontend types: ~60 → ~20 lines (67% reduction)
  • New entity cost: ~150+ lines → ~15 lines

All existing tests pass. Zero API behavior changes.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Refactor] DRY Violations - Reduce Code Duplication in API Routes and Repositories</issue_title>
<issue_description>## Summary

A comprehensive code analysis identified significant DRY (Don't Repeat Yourself) violations across the codebase. Addressing these will reduce maintenance burden, improve consistency, and cut total duplicated code by approximately 76% (~1,360 lines → ~330 lines).

Problem Statement

The current codebase contains extensive code duplication in:

Area Severity Files Affected Lines Duplicated
API Route Handlers 🔴 Critical 8 files ~800 lines
Swagger Documentation 🔴 Critical 8 files ~640 lines
Repository Classes 🟡 Moderate 7 files ~420 lines
TypeScript Interfaces (FE) 🟡 Moderate 3+ files ~60 lines
Error Handling 🟡 Moderate 8 files ~80 lines

Affected Files

API Routes (identical CRUD patterns)

  • api/src/routes/supplier.ts
  • api/src/routes/branch.ts
  • api/src/routes/headquarters.ts
  • api/src/routes/product.ts
  • api/src/routes/order.ts
  • api/src/routes/delivery.ts
  • api/src/routes/orderDetail.ts
  • api/src/routes/orderDetailDelivery.ts

Repositories (identical CRUD methods)

  • api/src/repositories/suppliersRepo.ts
  • api/src/repositories/branchesRepo.ts
  • api/src/repositories/productsRepo.ts
  • api/src/repositories/headquartersRepo.ts
  • api/src/repositories/ordersRepo.ts
  • api/src/repositories/deliveriesRepo.ts
  • api/src/repositories/orderDetailsRepo.ts

Frontend Types (duplicated interfaces)

  • frontend/src/components/entity/product/Products.tsx
  • frontend/src/components/admin/AdminProducts.tsx
  • frontend/src/components/entity/product/ProductForm.tsx

Proposed Solution

1. ⚡ Quick Win: Shared Frontend Types

Create frontend/src/types/models.ts with centralized type definitions.

Effort: < 1 hour | Impact: Eliminates ~60 lines of duplication

2. 📈 Create Generic CRUD Route Factory

Create api/src/utils/routeFactory.ts that generates standard CRUD routes.

Effort: 2-4 hours | Impact: Reduces ~800 lines → ~120 lines (85% reduction)

3. 📈 Create Base Repository Class

Create api/src/repositories/baseRepository.ts with shared CRUD operations.

Effort: 2-4 hours | Impact: Reduces ~420 lines → ~175 lines (58% reduction)

4. 🔧 Swagger Documentation Generator (Backlog)

Create utility to generate standard CRUD Swagger documentation.

Effort: 4-8 hours | Impact: Reduces ~640 lines of JSDoc duplication

Acceptance Criteria

  • Shared TypeScript types created in frontend/src/types/models.ts
  • BaseRepository class created and all repositories refactored to extend it
  • createCrudRouter factory created and all basic CRUD routes use it
  • All existing tests pass after refactoring
  • Custom route handlers (e.g., findByName, updateStatus) remain functional
  • No regression in API functionality

Testing Strategy

  1. Run existing tests before refactoring to establish baseline
  2. Create integration tests for generic implementations
  3. Verify all endpoints work via Swagger UI after changes

Additional Context

This refactoring aligns with the project's architecture guidelines and will make future entity additions significantly easier (new entities would require ~15 lines instead of ~150+ lines).


Generated from DRY violation analysis</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 5 commits January 26, 2026 11:41
Co-authored-by: webmaxru <1560278+webmaxru@users.noreply.github.com>
Co-authored-by: webmaxru <1560278+webmaxru@users.noreply.github.com>
Co-authored-by: webmaxru <1560278+webmaxru@users.noreply.github.com>
Co-authored-by: webmaxru <1560278+webmaxru@users.noreply.github.com>
Co-authored-by: webmaxru <1560278+webmaxru@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor code to reduce duplication in API routes and repositories Eliminate DRY violations with generic CRUD abstractions Jan 26, 2026
Copilot AI requested a review from webmaxru January 26, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor] DRY Violations - Reduce Code Duplication in API Routes and Repositories

2 participants