This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { and, eq } from 'drizzle-orm';
|
||||
import { and, eq, inArray } from 'drizzle-orm';
|
||||
|
||||
import {
|
||||
inventoryImages,
|
||||
inventoryItems,
|
||||
listings,
|
||||
products,
|
||||
} from '../../../infrastructure/database/schema.js';
|
||||
|
||||
@@ -29,5 +30,51 @@ export function createInventoryImageRepository(db) {
|
||||
|
||||
return rows.length;
|
||||
},
|
||||
|
||||
async listPublicByInventoryItemId(inventoryItemId) {
|
||||
return db
|
||||
.select({
|
||||
id: inventoryImages.id,
|
||||
mimeType: inventoryImages.mimeType,
|
||||
width: inventoryImages.width,
|
||||
height: inventoryImages.height,
|
||||
altText: inventoryImages.altText,
|
||||
sortOrder: inventoryImages.sortOrder,
|
||||
isPrimary: inventoryImages.isPrimary,
|
||||
processingStatus: inventoryImages.processingStatus,
|
||||
})
|
||||
.from(inventoryImages)
|
||||
.innerJoin(inventoryItems, eq(inventoryItems.id, inventoryImages.inventoryItemId))
|
||||
.innerJoin(products, eq(products.id, inventoryItems.productId))
|
||||
.innerJoin(listings, eq(listings.inventoryItemId, inventoryItems.id))
|
||||
.where(and(
|
||||
eq(inventoryImages.inventoryItemId, inventoryItemId),
|
||||
eq(inventoryItems.status, 'ACTIVE'),
|
||||
inArray(listings.status, ['AVAILABLE', 'PENDING']),
|
||||
eq(inventoryImages.processingStatus, 'COMPLETED'),
|
||||
))
|
||||
.orderBy(inventoryImages.sortOrder);
|
||||
},
|
||||
|
||||
async findPublicById(imageId) {
|
||||
const [image] = await db
|
||||
.select({
|
||||
id: inventoryImages.id,
|
||||
storageKey: inventoryImages.storageKey,
|
||||
mimeType: inventoryImages.mimeType,
|
||||
})
|
||||
.from(inventoryImages)
|
||||
.innerJoin(inventoryItems, eq(inventoryItems.id, inventoryImages.inventoryItemId))
|
||||
.innerJoin(products, eq(products.id, inventoryItems.productId))
|
||||
.innerJoin(listings, eq(listings.inventoryItemId, inventoryItems.id))
|
||||
.where(and(
|
||||
eq(inventoryImages.id, imageId),
|
||||
eq(inventoryItems.status, 'ACTIVE'),
|
||||
inArray(listings.status, ['AVAILABLE', 'PENDING']),
|
||||
eq(inventoryImages.processingStatus, 'COMPLETED'),
|
||||
));
|
||||
|
||||
return image ?? null;
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export async function registerPublicImageRoutes(app, options) {
|
||||
const { publicImageService } = options;
|
||||
|
||||
app.get('/public/images/:id', async (request, reply) => {
|
||||
const image = await publicImageService.getContent(request.params.id);
|
||||
return reply.type(image.mimeType).send(image.data);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { createApplicationError } from '../../../shared/errors/application-error.js';
|
||||
|
||||
export function createPublicImageService({ inventoryImageRepository, imageStorage }) {
|
||||
return {
|
||||
async listForInventoryItem(inventoryItemId) {
|
||||
const images = await inventoryImageRepository.listPublicByInventoryItemId(inventoryItemId);
|
||||
return images.map((image) => ({
|
||||
...image,
|
||||
url: `/api/v1/public/images/${image.id}`,
|
||||
}));
|
||||
},
|
||||
|
||||
async getContent(imageId) {
|
||||
const image = await inventoryImageRepository.findPublicById(imageId);
|
||||
|
||||
if (!image) {
|
||||
throw createApplicationError('IMAGE_NOT_FOUND', 'Image was not found.', 404);
|
||||
}
|
||||
|
||||
return { ...image, data: await imageStorage.get(image.storageKey) };
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { createApplicationError } from '../../../shared/errors/application-error.js';
|
||||
|
||||
export function createPublicInventoryService({ inventoryItemRepository }) {
|
||||
const noOpPublicImageService = Object.freeze({ async listForInventoryItem() { return []; } });
|
||||
|
||||
export function createPublicInventoryService({ inventoryItemRepository, publicImageService = noOpPublicImageService }) {
|
||||
return {
|
||||
async list(input = {}) {
|
||||
return inventoryItemRepository.searchPublic({
|
||||
@@ -16,7 +18,10 @@ export function createPublicInventoryService({ inventoryItemRepository }) {
|
||||
throw createApplicationError('INVENTORY_NOT_FOUND', 'Inventory item was not found.', 404);
|
||||
}
|
||||
|
||||
return item;
|
||||
return {
|
||||
...item,
|
||||
images: await publicImageService.listForInventoryItem(item.id),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { createApplicationError } from '../../../shared/errors/application-error.js';
|
||||
|
||||
export function createPublicListingService({ listingRepository }) {
|
||||
const noOpPublicImageService = Object.freeze({ async listForInventoryItem() { return []; } });
|
||||
|
||||
export function createPublicListingService({ listingRepository, publicImageService = noOpPublicImageService }) {
|
||||
return {
|
||||
async list(input = {}) {
|
||||
return listingRepository.searchPublic({
|
||||
@@ -17,7 +19,10 @@ export function createPublicListingService({ listingRepository }) {
|
||||
throw createApplicationError('LISTING_NOT_FOUND', 'Listing was not found.', 404);
|
||||
}
|
||||
|
||||
return listing;
|
||||
return {
|
||||
...listing,
|
||||
images: await publicImageService.listForInventoryItem(listing.inventoryItemId),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user