import { ShopifyStoreConnector, type ConnectorMeta, type RawRecordLike } from '@rareindex/connectors'; import type { NormalizedRecord } from '@rareindex/shared'; /** * Video Game Trader (videogametrader.com) — Shopify storefront read through the shared Shopify adapter * (collections → taxonomy mapping and title rules live in meta.json). This subclass only enriches the * condition block from the store's own vocabulary: titles end with " - - Used (Complete)", * " - Used (Loose)", " - New" and products carry "Condition:…" tags. */ export function completenessFromTitle(title: string, tags: string[] = []): { completeness: string | null; conditionRaw: string | null } { const cond = tags.find((t) => /^Condition:/i.test(t))?.replace(/^Condition:/i, '').trim() ?? title.match(/-\s*((?:Used|New|NEW|Preowned|Pre-owned|Brand New|Sealed)[^-]*)$/)?.[1]?.trim() ?? null; const c = (cond ?? title).toLowerCase(); let completeness: string | null = null; if (/\b(sealed|brand new|\bnew\b)/.test(c) && !/used/.test(c)) completeness = 'sealed'; else if (/complete|cib|\(cib\)/.test(c)) completeness = 'cib'; else if (/loose|cart(?:ridge)? only|disc only|game only/.test(c)) completeness = 'loose'; else if (/box only|no game|manual only/.test(c)) completeness = 'box_only'; return { completeness, conditionRaw: cond }; } export class VideoGameTraderConnector extends ShopifyStoreConnector { override async normalize(raw: RawRecordLike): Promise { const out = await super.normalize(raw); for (const r of out) { if (r.kind !== 'listing') continue; const tags = Array.isArray(r.attributes.metadata.tags) ? (r.attributes.metadata.tags as string[]) : []; const c = completenessFromTitle(r.rawTitle, tags); r.condition = { condition: r.condition.condition, conditionRaw: c.conditionRaw ?? r.condition.conditionRaw, completeness: c.completeness ?? r.condition.completeness }; // platform tag → attributes.set when the title pattern did not catch it const platform = tags.find((t) => /^Platform:/i.test(t))?.replace(/^Platform:/i, '').trim(); if (platform && !r.attributes.set) r.attributes.set = platform; if (platform) r.attributes.metadata.platform = platform; // strip the store's condition suffix from the asset name r.attributes.name = r.attributes.name.replace(/\s*-\s*(?:Used|New|NEW|Preowned|Pre-owned|Brand New|Sealed)\b.*$/i, '').replace(/\s*\*\s*NEW\s*$/i, '').replace(/\s*[|-]\s*[^|-]{2,40}$/, (m) => (platform && m.toLowerCase().includes(platform.toLowerCase().slice(0, 4)) ? '' : m)).trim() || r.attributes.name; } return out; } } export default (meta: ConnectorMeta) => new VideoGameTraderConnector(meta);