Fetching products with filenames
A creative approach will be needed to fetch the filenames.
Now, we should fetch the products together with their images' filenames. Unfortunately, this cannot be achieved with the @Expose()
decorator, as the class-transformer library does not support asynchronous transformations. However, there is an event listener that can be used: afterLoad()
. With a suggestive name, it executes after an entity is loaded. This way, we can perform this process in the file products/subscribers/products.subscriber. We should just remember to add it to the providers
in the ProductsModule
. Below, we can see its basic template.
@EventSubscriber()
export class ProductsSubscriber implements EntitySubscriberInterface<Product> {
constructor(private readonly dataSource: DataSource) {
dataSource.subscribers.push(this);
}
listenTo() {
return Product;
}
}
Here, we'll first create a private method that receives the id
of a product
and returns the filenames
of its images
, if the respective directory exists.
private async getImagesFilenames(id: number) {
const { BASE, IMAGES } = FilePath.Products;
const path = join(BASE, id.toString(), IMAGES);
if (!(await pathExists(join(BASE_PATH, path)))) return;
return this.storageService.getDirFilenames(path);
}
And above it, we can then use the afterLoad()
event listener to create a field for these filenames
when fetching products
. This may not be the most ideal way, but as the @Expose()
decorator has the aforementioned flaw, this may be a viable alternative.
async afterLoad(entity: Product) {
const product = entity;
const imagesFilenames = await this.getImagesFilenames(product.id);
product[this.IMAGES_FILENAMES_KEY] = imagesFilenames;
}
private readonly IMAGES_FILENAMES_KEY = 'imagesFilenames';
Commit - Retrieving products with images filenames
With this, the last remaining step is to make the images in the upload folder become directly available just by accessing their paths.
Last updated