feat: surface automation option details
This commit is contained in:
62
server.js
62
server.js
@@ -63,6 +63,32 @@ function normalizeKey(value) {
|
||||
.replace(/^-+|-+$/g, '');
|
||||
}
|
||||
|
||||
function toTextList(value) {
|
||||
const items = Array.isArray(value) ? value : value == null ? [] : [value];
|
||||
|
||||
return [...new Set(items.flatMap((item) => {
|
||||
if (Array.isArray(item)) {
|
||||
return item;
|
||||
}
|
||||
|
||||
if (item && typeof item === 'object') {
|
||||
return [
|
||||
item.label,
|
||||
item.name,
|
||||
item.text,
|
||||
item.title,
|
||||
item.value,
|
||||
item.summary,
|
||||
item.description,
|
||||
].filter(Boolean);
|
||||
}
|
||||
|
||||
return [item];
|
||||
})
|
||||
.map((item) => String(item).trim())
|
||||
.filter(Boolean))];
|
||||
}
|
||||
|
||||
function readJsonLines(filePath) {
|
||||
if (!fs.existsSync(filePath)) return [];
|
||||
|
||||
@@ -162,6 +188,13 @@ function loadPriceHistoryState() {
|
||||
source: point.source || null,
|
||||
sourceUrl: point.sourceUrl || point.url || null,
|
||||
note: point.note || point.description || null,
|
||||
availability: point.availability || point.status || null,
|
||||
decisionNote: point.decisionNote || point.note || point.description || null,
|
||||
highlights: toTextList(point.highlights || point.summaryBullets || point.bullets),
|
||||
features: toTextList(point.features || point.featureHighlights || point.featureLabels),
|
||||
amenities: toTextList(point.amenities || point.amenityHighlights || point.amenityLabels),
|
||||
inclusions: toTextList(point.inclusions || point.includes || point.perks),
|
||||
limitations: toTextList(point.limitations || point.tradeoffs || point.caveats),
|
||||
};
|
||||
|
||||
if (!seriesByKey.has(key)) seriesByKey.set(key, []);
|
||||
@@ -196,12 +229,41 @@ function getPriceHistoryForOption(option, priceHistoryState) {
|
||||
function decorateOptionWithPriceHistory(option, priceHistoryState) {
|
||||
const priceHistory = getPriceHistoryForOption(option, priceHistoryState);
|
||||
const latestPricePoint = priceHistory.at(-1) || null;
|
||||
const optionDetails = toTextList(option.details);
|
||||
const automationHighlights = toTextList(latestPricePoint?.highlights);
|
||||
const automationFeatures = toTextList(latestPricePoint?.features);
|
||||
const automationAmenities = toTextList(latestPricePoint?.amenities);
|
||||
const automationInclusions = toTextList(latestPricePoint?.inclusions);
|
||||
const automationLimitations = toTextList(latestPricePoint?.limitations);
|
||||
const decisionDetails = [
|
||||
...optionDetails,
|
||||
...automationHighlights,
|
||||
...automationFeatures,
|
||||
...automationAmenities,
|
||||
...automationInclusions,
|
||||
...automationLimitations,
|
||||
];
|
||||
|
||||
return {
|
||||
...option,
|
||||
priceHistory,
|
||||
latestPricePoint,
|
||||
currentPrice: latestPricePoint?.price ?? null,
|
||||
decisionDetails: [...new Set(decisionDetails)],
|
||||
automationInsights: latestPricePoint ? {
|
||||
currentPrice: latestPricePoint.price,
|
||||
currency: latestPricePoint.currency || 'USD',
|
||||
displayPrice: latestPricePoint.displayPrice || null,
|
||||
source: latestPricePoint.source || null,
|
||||
sourceUrl: latestPricePoint.sourceUrl || null,
|
||||
availability: latestPricePoint.availability || null,
|
||||
decisionNote: latestPricePoint.decisionNote || null,
|
||||
highlights: automationHighlights,
|
||||
features: automationFeatures,
|
||||
amenities: automationAmenities,
|
||||
inclusions: automationInclusions,
|
||||
limitations: automationLimitations,
|
||||
} : null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user