Repository: medusajs/medusa
File: packages/modules/product/src/services/product-module-service.ts (TypeScript)

Code before:

  __joinerConfig(): ModuleJoinerConfig {
    return joinerConfig
  }

  @InjectManager()
  // @ts-ignore
  async retrieveProduct(
    productId: string,
    config?: FindConfig<ProductTypes.ProductDTO>,
    @MedusaContext() sharedContext?: Context
  ): Promise<ProductTypes.ProductDTO> {
    const shouldLoadVariantImages =
      config?.relations?.includes("variants.images")

    // Ensure we load necessary relations
    const relations = [...(config?.relations || [])]
    if (shouldLoadVariantImages) {
      if (!relations.includes("variants")) {
        relations.push("variants")
      }
      if (!relations.includes("images")) {
        relations.push("images")
      }
      // Need to load image.variants to filter properly
      relations.push("images.variants")
    }

    const product = await this.productService_.retrieve(
      productId,
      this.getProductFindConfig_({ ...config, relations }),
      sharedContext
    )

    if (shouldLoadVariantImages && product.variants && product.images) {
      this.buildVariantImagesFromProduct(product.variants, product.images)
    }

    return this.baseRepository_.serialize<ProductTypes.ProductDTO>(product)
  }

  @InjectManager()
  // @ts-ignore
  async listProducts(
    filters?: ProductTypes.FilterableProductProps,
    config?: FindConfig<ProductTypes.ProductDTO>,
    sharedContext?: Context
  ): Promise<ProductTypes.ProductDTO[]> {
    const shouldLoadVariantImages =
      config?.relations?.includes("variants.images")


Review comment (suggestion):
self-review: fetch pivot map in `buildVariantImagesFromProduct` instead of loading variants for each image

Code after:
    this.eventBusModuleService_ = eventBusModuleService
  }

  __joinerConfig(): ModuleJoinerConfig {
    return joinerConfig
  }

  @InjectManager()
  // @ts-ignore
  async retrieveProduct(
    productId: string,
    config?: FindConfig<ProductTypes.ProductDTO>,
    @MedusaContext() sharedContext?: Context
  ): Promise<ProductTypes.ProductDTO> {
    const relationsSet = new Set(config?.relations ?? [])
    const shouldLoadVariantImages = relationsSet.has("variants.images")
    if (shouldLoadVariantImages) {
      relationsSet.add("variants")
      relationsSet.add("images")
    }

    const product = await this.productService_.retrieve(
      productId,
      this.getProductFindConfig_({
        ...config,
        relations: Array.from(relationsSet),
      }),
      sharedContext
    )

    if (shouldLoadVariantImages && product.variants && product.images) {
      await this.buildVariantImagesFromProduct(
        product.variants,
        product.images,
        sharedContext
      )
    }

    return this.baseRepository_.serialize<ProductTypes.ProductDTO>(product)
  }

  @InjectManager()
  // @ts-ignore
  async listProducts(
    filters?: ProductTypes.FilterableProductProps,
    config?: FindConfig<ProductTypes.ProductDTO>,
    sharedContext?: Context
  ): Promise<ProductTypes.ProductDTO[]> {
    const relationsSet = new Set(config?.relations ?? [])
    const shouldLoadVariantImages = relationsSet.has("variants.images")
    if (shouldLoadVariantImages) {