import { amazon_product, amazon_search_item, amazon_review } from '../models/index.js'; import { safe_json_stringify } from './json_utils.js'; function build_batch_key(prefix) { return `${prefix}_${Date.now()}_${Math.random().toString().slice(2, 8)}`; } function pick_asin_from_url(url) { if (!url) return null; const m = String(url).match(/\/dp\/([A-Z0-9]{8,16})/i); return m && m[1] ? m[1].toUpperCase() : null; } export async function persist_amazon_result(result) { if (!result || !result.stage) { return; } if (result.stage === 'detail') { const asin = result.asin || pick_asin_from_url(result.url); if (!asin) { return; } await amazon_product.upsert({ asin, url: result.url || '', title: result.title || null, price: result.price || null, sku: result.sku || null, sku_color: result.sku_color || null, sku_size: result.sku_size || null, brand_line: result.brand_line || null, brand_store_url: result.brand_store_url || null, ac_badge: result.ac_badge || null, bestseller_hint: result.bestseller_hint || null, delivery_hint: result.delivery_hint || null, social_proof: result.social_proof || null, sustainability_hint: result.sustainability_hint || null, rating_stars: result.rating_stars || null, review_count_text: result.review_count_text || null, main_image: result.main_image || null, images_json: safe_json_stringify(result.images || []), bullets_json: safe_json_stringify(result.bullets || []), product_info_json: safe_json_stringify(result.product_info || {}), detail_extra_lines_json: safe_json_stringify(result.detail_extra_lines || []) }); return; } if (result.stage === 'list') { const batch_key = build_batch_key('list'); const items = Array.isArray(result.items) ? result.items : []; for (const it of items) { const asin = it.asin || pick_asin_from_url(it.url); if (!asin || !it.url) continue; await amazon_search_item.create({ asin, url: it.url, title: it.title || null, price: it.price || null, rating: typeof it.rating === 'number' ? it.rating : null, rating_text: it.rating_text || null, review_count: typeof it.review_count === 'number' ? it.review_count : null, review_count_text: it.review_count_text || null, rank_index: typeof it.index === 'number' ? it.index : null, batch_key, batch_total: typeof result.total === 'number' ? result.total : null, batch_limit: typeof result.limit === 'number' ? result.limit : null }); } return; } if (result.stage === 'reviews') { const batch_key = build_batch_key('reviews'); const asin = pick_asin_from_url(result.url); const items = Array.isArray(result.items) ? result.items : []; for (const it of items) { const review_id = it.review_id; if (!review_id) continue; const asin_value = asin || pick_asin_from_url(it.url) || pick_asin_from_url(result.url); await amazon_review.upsert({ asin: asin_value || null, url: result.url || '', review_id, author: it.author || null, title: it.title || null, body: it.body || null, rating_text: it.rating_text || null, review_date: it.date || null, review_index: typeof it.index === 'number' ? it.index : null, batch_key, batch_total: typeof result.total === 'number' ? result.total : null, batch_limit: typeof result.limit === 'number' ? result.limit : null }); } } }