Skip to content

[Refactoring] Services: Extract MetaCatalogManager (1454 lines) into focused API client modules #226

@syed-reza98

Description

@syed-reza98

Problem

The MetaCatalogManager class in src/lib/integrations/facebook/catalog-manager.ts has grown to 1,454 lines and handles multiple responsibilities:

  • Batch operations (create, update, delete)
  • Quick update operations (inventory, prices)
  • Product retrieval and listing
  • Batch status checking
  • HTTP request handling and retry logic
  • URL building and authentication
  • Error handling

This violates the Single Responsibility Principle and makes the code difficult to test, maintain, and extend.

Current Code Location

  • File: src/lib/integrations/facebook/catalog-manager.ts (lines 1-1454)
  • Class: MetaCatalogManager (824+ lines, spanning lines 488-1312)
  • Complexity: High

Proposed Refactoring

Benefits

  • Improved testability: Each module can be tested independently
  • Easier maintenance: Changes to one operation type won't affect others
  • Better code organization: Clear separation of concerns
  • Reduced cognitive load: Each module focuses on one specific task
  • Reusability: Individual modules can be composed differently for different use cases

Suggested Approach

  1. Extract HTTP Client Module (meta-catalog-client.ts)

    • Move HTTP request handling, retry logic, authentication, URL building
    • Keep the core transport layer separate from business logic
  2. Extract Batch Operations Module (meta-catalog-batch.ts)

    • batchCreate(), batchUpdate(), batchDelete()
    • sendBatch() and batch request formatting
  3. Extract Quick Updates Module (meta-catalog-updates.ts)

    • updateInventory(), updatePrices()
    • Optimized for high-frequency sync operations
  4. Extract Product Retrieval Module (meta-catalog-products.ts)

    • getProduct(), listProducts(), getProductCount()
    • Read-only operations with pagination support
  5. Extract Status Tracking Module (meta-catalog-status.ts)

    • getBatchStatus()
    • Async status polling and monitoring
  6. Keep Facade Class (catalog-manager.ts)

    • Maintain backward compatibility
    • Delegate to focused modules
    • Provide high-level API for common workflows

Code Example

Before:

// 1454 lines in one file with a single 824-line class
export class MetaCatalogManager {
  async batchUpdate(products: CatalogProduct[]): Promise(BatchResponse) { /* ... */ }
  async updateInventory(updates: InventoryUpdate[]): Promise(BatchResponse) { /* ... */ }
  async getProduct(retailerId: string): Promise(CatalogProductResponse | null) { /* ... */ }
  async getBatchStatus(handle: string): Promise(BatchStatusResponse) { /* ... */ }
  private async makeRequest(T)(url: string, options?: RequestInit): Promise(T) { /* ... */ }
  // ... 20+ more methods
}

After:

// meta-catalog-client.ts (~200 lines)
export class MetaCatalogClient {
  async makeRequest(T)(url: string, options?: RequestInit): Promise(T) { /* ... */ }
  buildUrl(path: string, params?: Record(string, string | number)): string { /* ... */ }
  generateAppSecretProof(accessToken: string, appSecret: string): string { /* ... */ }
}

// meta-catalog-batch.ts (~300 lines)
export class MetaCatalogBatch {
  constructor(private client: MetaCatalogClient, private catalogId: string) {}
  
  async batchCreate(products: CatalogProduct[]): Promise(BatchResponse) { /* ... */ }
  async batchUpdate(products: CatalogProduct[]): Promise(BatchResponse) { /* ... */ }
  async batchDelete(retailerIds: string[]): Promise(BatchResponse) { /* ... */ }
}

// meta-catalog-updates.ts (~200 lines)
export class MetaCatalogUpdates {
  constructor(private client: MetaCatalogClient, private catalogId: string) {}
  
  async updateInventory(updates: InventoryUpdate[]): Promise(BatchResponse) { /* ... */ }
  async updatePrices(updates: PriceUpdate[]): Promise(BatchResponse) { /* ... */ }
}

// meta-catalog-products.ts (~250 lines)
export class MetaCatalogProducts {
  constructor(private client: MetaCatalogClient, private catalogId: string) {}
  
  async getProduct(retailerId: string): Promise(CatalogProductResponse | null) { /* ... */ }
  async listProducts(limit?: number, cursor?: string): Promise(ProductListResponse) { /* ... */ }
  async getProductCount(): Promise(number) { /* ... */ }
}

// meta-catalog-status.ts (~150 lines)
export class MetaCatalogStatus {
  constructor(private client: MetaCatalogClient) {}
  
  async getBatchStatus(handle: string): Promise(BatchStatusResponse) { /* ... */ }
}

// catalog-manager.ts (~200 lines - Facade)
export class MetaCatalogManager {
  private client: MetaCatalogClient;
  private batch: MetaCatalogBatch;
  private updates: MetaCatalogUpdates;
  private products: MetaCatalogProducts;
  private status: MetaCatalogStatus;
  
  constructor(config: CatalogManagerConfig) {
    this.client = new MetaCatalogClient(config);
    this.batch = new MetaCatalogBatch(this.client, config.catalogId);
    this.updates = new MetaCatalogUpdates(this.client, config.catalogId);
    this.products = new MetaCatalogProducts(this.client, config.catalogId);
    this.status = new MetaCatalogStatus(this.client);
  }
  
  // Backward-compatible delegation methods
  async batchUpdate(products: CatalogProduct[]): Promise(BatchResponse) {
    return this.batch.batchUpdate(products);
  }
  
  async updateInventory(updates: InventoryUpdate[]): Promise(BatchResponse) {
    return this.updates.updateInventory(updates);
  }
  // ... delegate to focused modules
}

Impact Assessment

  • Effort: High - Estimated 3-4 days to refactor and test
  • Risk: Medium - Good test coverage and interface preservation will minimize risk
  • Benefit: High - Significantly improves code organization and maintainability
  • Priority: High - This is one of the largest files in the codebase

Related Files

  • src/lib/integrations/facebook/catalog-manager.ts (1454 lines - to be split)
  • src/app/api/integrations/facebook/sync/route.ts (uses catalog manager)
  • src/lib/integrations/facebook/product-sync-service.ts (uses catalog manager)

Testing Strategy

  1. Create comprehensive unit tests for each new module
  2. Maintain integration tests that verify the facade still works
  3. Add focused tests for error handling in each module
  4. Verify backward compatibility with existing API consumers
  5. Test retry logic separately in HTTP client module
  6. Test batch chunking in batch operations module

AI generated by Daily Codebase Analyzer - Semantic Function Extraction & Refactoring

  • expires on Feb 27, 2026, 8:37 PM UTC

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions