All files / src/types product.ts

81.81% Statements 72/88
25% Branches 1/4
25% Functions 1/4
81.81% Lines 72/88

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 891x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x     2x 2x     2x 1x 1x             1x 1x 1x 1x 1x 1x 1x       1x 1x 1x 1x 1x 1x       1x 1x 1x 1x 1x 1x 1x  
export type Product = {
  title: string;
  reviews?: number;
  rating?: number;
  averageRating?: number;
  price: number;
  discountedPrice: number;
  stock?: number;
  description?: string;
  id: number;
  imgs?: {
    thumbnails: string[];
    previews: string[];
  };
  details?: string[];
  specifications?: ProductSpecifications;
};
 
// Product specifications as flexible JSON object
export interface ProductSpecifications {
  [key: string]: string | number | boolean;
}
 
// Database Product model with specifications and details
export interface DBProduct {
  id: number;
  title: string;
  description?: string | null;
  price: number;
  discountedPrice: number;
  stock: number;
  sku?: string | null;
  categoryId: number;
  specifications?: ProductSpecifications | null;
  details?: string | null; // JSON string array
  createdAt: Date;
  updatedAt: Date;
}
 
// Product with parsed details array
export interface ProductWithDetails extends Omit<DBProduct, 'details'> {
  details?: string[] | null;
}
 
// Helper function to parse details from JSON string to array
export function parseProductDetails(detailsString?: string | null): string[] {
  if (!detailsString) return [];
  try {
    const parsed = JSON.parse(detailsString);
    return Array.isArray(parsed) ? parsed : [];
  } catch {
    return [];
  }
}
 
// Helper function to format specifications for display
export function formatSpecificationValue(value: string | number | boolean): string {
  if (typeof value === 'boolean') {
    return value ? 'Yes' : 'No';
  }
  return String(value);
}
 
// Type guards for discriminating between legacy and database products
/**
 * Type guard to check if a product is from the database
 * @param product - Product to check
 * @returns true if product has database-specific fields
 */
export function isDBProduct(product: unknown): product is DBProduct {
  return typeof product === 'object' && product !== null && 'categoryId' in product && 'sku' in product;
}
 
/**
 * Type guard to check if a product uses the legacy format
 * @param product - Product to check
 * @returns true if product has legacy imgs structure
 */
export function isLegacyProduct(product: unknown): product is Product {
  return typeof product === 'object' && product !== null && 'imgs' in product && !('categoryId' in product);
}
 
// Union type for components that can accept both formats during migration
/**
 * Union type for components being migrated from legacy to database format
 * Use this type when a component needs to support both Product and DBProduct
 */
export type AnyProduct = Product | DBProduct;