import type { MarketApiFailureReason, MarketRecord, MarketRowSnapshot } from "./types"; import type { AfterSearchRates } from "./types"; export function createMarketResultStore() { const records = new Map(); return { getRecord(authorId: string) { return records.get(authorId) ?? null; }, listRecords() { return Array.from(records.values()); }, setAuthorFailed(authorId: string, reason: MarketApiFailureReason) { const existingRecord = ensureRecord(authorId); existingRecord.status = "failed"; existingRecord.failureReason = reason; }, setAuthorLoading(authorId: string) { const existingRecord = ensureRecord(authorId); existingRecord.status = "loading"; delete existingRecord.failureReason; }, setAuthorSuccess(authorId: string, rates: AfterSearchRates) { const existingRecord = ensureRecord(authorId); existingRecord.status = "success"; existingRecord.rates = { ...existingRecord.rates, ...rates }; delete existingRecord.failureReason; }, upsertMarketRow(row: MarketRowSnapshot) { const existingRecord = records.get(row.authorId); if (existingRecord) { existingRecord.authorName = mergeStringValue(existingRecord.authorName, row.authorName) ?? existingRecord.authorName; existingRecord.location = mergeStringValue( existingRecord.location, row.location ); existingRecord.price21To60s = mergeStringValue( existingRecord.price21To60s, row.price21To60s ); existingRecord.exportFields = mergeFieldMap( existingRecord.exportFields, row.exportFields ); existingRecord.hasDirectRatesSource = existingRecord.hasDirectRatesSource || row.hasDirectRatesSource; existingRecord.rates = mergeFieldMap(existingRecord.rates, row.rates); return existingRecord; } const nextRecord: MarketRecord = { ...row, status: "idle" }; records.set(row.authorId, nextRecord); return nextRecord; } }; function ensureRecord(authorId: string): MarketRecord { const existingRecord = records.get(authorId); if (existingRecord) { return existingRecord; } const nextRecord: MarketRecord = { authorId, authorName: authorId, status: "idle" }; records.set(authorId, nextRecord); return nextRecord; } } function mergeFieldMap>( current: T | undefined, incoming: T | undefined ): T | undefined { if (!current && !incoming) { return undefined; } const merged = { ...(current ?? {}) } as Record; Object.entries(incoming ?? {}).forEach(([key, value]) => { const currentValue = merged[key]; if (!hasTextValue(currentValue)) { merged[key] = value; } }); return merged as T; } function mergeStringValue( current: string | undefined, incoming: string | undefined ): string | undefined { if (!hasTextValue(current)) { return incoming ?? current; } return current; } function hasTextValue(value: string | undefined): boolean { return typeof value === "string" && value.trim().length > 0; }