110 lines
3.6 KiB
JavaScript
110 lines
3.6 KiB
JavaScript
const express = require("express")
|
|
const router = express.Router()
|
|
|
|
const requireAuth = require("../middleware/requireAuth")
|
|
const optionalAuth = require("../middleware/optionalAuth")
|
|
const { validate } = require("../middleware/validate.middleware")
|
|
const { endpoints } = require("@shared/contracts")
|
|
const { getSellerByName, getDealsBySellerName, getActiveSellers } = require("../services/seller.service")
|
|
const { findSellerFromLink } = require("../services/sellerLookup.service")
|
|
const { getProductPreviewFromUrl } = require("../services/productPreview.service")
|
|
const { mapSellerToSellerDetailsResponse } = require("../adapters/responses/sellerDetails.adapter")
|
|
const { mapPaginatedDealsToDealCardResponse } = require("../adapters/responses/dealCard.adapter")
|
|
const { getClientIp } = require("../utils/requestInfo")
|
|
const { queueDealImpressions } = require("../services/redis/dealAnalytics.service")
|
|
|
|
const { seller, deals } = endpoints
|
|
|
|
const buildViewer = (req) =>
|
|
req.auth ? { userId: req.auth.userId, role: req.auth.role } : null
|
|
|
|
const listQueryValidator = validate(deals.dealsListRequestSchema, "query", "validatedDealListQuery")
|
|
|
|
router.post("/from-link", requireAuth, async (req, res) => {
|
|
try {
|
|
const sellerUrl = req.body.url
|
|
if (!sellerUrl) return res.status(400).json({ error: "url parametresi zorunlu" })
|
|
const [sellerLookup, product] = await Promise.all([
|
|
findSellerFromLink(sellerUrl),
|
|
getProductPreviewFromUrl(sellerUrl),
|
|
])
|
|
|
|
const response = seller.sellerLookupResponseSchema.parse(
|
|
sellerLookup
|
|
? {
|
|
found: true,
|
|
seller: {
|
|
id: sellerLookup.id,
|
|
name: sellerLookup.name,
|
|
url: sellerLookup.url ?? null,
|
|
},
|
|
product,
|
|
}
|
|
: { found: false, seller: null, product }
|
|
)
|
|
|
|
return res.json(response)
|
|
} catch (e) {
|
|
console.error(e)
|
|
res.status(500).json({ error: "Sunucu hatasi" })
|
|
}
|
|
})
|
|
|
|
router.get("/", async (req, res) => {
|
|
try {
|
|
const sellers = await getActiveSellers()
|
|
res.json(sellers)
|
|
} catch (e) {
|
|
const status = e.statusCode || 500
|
|
res.status(status).json({ error: e.message || "Sunucu hatasi" })
|
|
}
|
|
})
|
|
|
|
router.get("/:sellerName", async (req, res) => {
|
|
try {
|
|
const sellerName = req.params.sellerName
|
|
const sellerInfo = await getSellerByName(sellerName)
|
|
if (!sellerInfo) return res.status(404).json({ error: "Seller bulunamadi" })
|
|
|
|
res.json(mapSellerToSellerDetailsResponse(sellerInfo))
|
|
} catch (e) {
|
|
const status = e.statusCode || 500
|
|
res.status(status).json({ error: e.message || "Sunucu hatasi" })
|
|
}
|
|
})
|
|
|
|
router.get("/:sellerName/deals", optionalAuth, listQueryValidator, async (req, res) => {
|
|
try {
|
|
const sellerName = req.params.sellerName
|
|
const { q, page, limit } = req.validatedDealListQuery
|
|
|
|
const { payload } = await getDealsBySellerName(sellerName, {
|
|
page,
|
|
limit,
|
|
filters: req.query,
|
|
viewer: buildViewer(req),
|
|
})
|
|
|
|
const response = mapPaginatedDealsToDealCardResponse(payload)
|
|
const dealIds = payload?.results?.map((deal) => deal.id) || []
|
|
queueDealImpressions({
|
|
dealIds,
|
|
userId: req.auth?.userId ?? null,
|
|
ip: getClientIp(req),
|
|
}).catch((err) => console.error("Deal impression queue failed:", err?.message || err))
|
|
res.json({
|
|
page: response.page,
|
|
total: response.total,
|
|
totalPages: response.totalPages,
|
|
results: response.results,
|
|
minPrice: payload?.minPrice ?? null,
|
|
maxPrice: payload?.maxPrice ?? null,
|
|
})
|
|
} catch (e) {
|
|
const status = e.statusCode || 500
|
|
res.status(status).json({ error: e.message || "Sunucu hatasi" })
|
|
}
|
|
})
|
|
|
|
module.exports = router
|