/** Live fixture capture for magi: two series pages (Pokémon, Yu-Gi-Oh! incl. a SOLD item) + one sold item page. Usage: pnpm tsx connectors/api/magi/_capture.ts */ import { mkdirSync, writeFileSync } from 'node:fs'; import path from 'node:path'; import { fixtureDir, saveFixture } from '@rareindex/connectors/testing'; import meta from './meta.json' with { type: 'json' }; import { parseItemPage, parseSeriesPage, type MagiPayload, type MagiSeed } from './index.js'; import { HTML_HEADERS } from '../_g1-cards-eu-jp-lib/index.js'; const SITE = 'https://magi.camp'; const text = async (u: string) => (await fetch(u, { headers: HTML_HEADERS })).text(); const wait = (ms: number) => new Promise((r) => setTimeout(r, ms)); mkdirSync(fixtureDir('magi'), { recursive: true }); const seeds = meta.config.seeds as MagiSeed[]; let soldUrl: string | null = null; for (const [series, name, keep] of [['31', 'pokemon-series-page1', 24], ['34', 'yugioh-series-page1', 24]] as const) { const seed = seeds.find((s) => s.series === series)!; const url = `${SITE}/series/${series}/items`; const doc = await text(url); if (series === '31') writeFileSync(path.join(fixtureDir('magi'), 'series-page.html'), doc); const { items, hasNext, heading } = parseSeriesPage(doc); // keep the first `keep` items but make sure a SOLD item is included when the page has one const sold = items.find((i) => i.sold); const kept = items.slice(0, keep); if (sold && !kept.includes(sold)) kept[kept.length - 1] = sold; if (sold) soldUrl = soldUrl ?? sold.url; const payload: MagiPayload = { type: 'list', seed, page: 1, items: kept }; saveFixture('magi', name, { raw: { url, externalId: `series:${series}:p1`, kind: 'listing', engine: 'api', fetchedAt: new Date(), payload }, expect: { minCount: 5, kinds: ['listing'], requiredFields: ['price', 'attributes.name'] }, note: `Live capture ${new Date().toISOString().slice(0, 10)} — ${url} (${heading}; ${items.length} items, hasNext=${hasNext}, sold on page: ${items.filter((i) => i.sold).length}; first ${kept.length} kept)`, }); console.log(name, heading, items.length, hasNext, kept[0], sold?.title); await wait(4000); } if (soldUrl) { const doc = await text(soldUrl); const item = parseItemPage(doc, soldUrl)!; const payload: MagiPayload = { type: 'item', seed: null, ...item }; saveFixture('magi', 'sold-item-page', { raw: { url: soldUrl, externalId: item.id, kind: 'listing', engine: 'api', fetchedAt: new Date(), payload }, expect: { minCount: 0, kinds: ['listing'] }, note: `Live capture ${new Date().toISOString().slice(0, 10)} — ${soldUrl} JSON-LD Product (availability ${item.availability}); lookup path`, }); console.log('sold item', item); }