#!/usr/bin/env bun // Refreshes the bundled PPP dataset of `storebound prices ppp` from the World Bank API (read-only public API, no key). // bun tools/update-ppp.ts fetch PA.NUS.PPP + PA.NUS.FCRF, rewrite cli/data/ppp-worldbank.json (retrieved = today) // bun tools/update-ppp.ts --check print the bundled file's age and data year, write nothing // bun tools/update-ppp.ts --bigmac [--project ] [--dry] // download The Economist Big Mac index into /.storebound/ppp-bigmac.json // (not bundled: the repo's licence leaves third-party data out; same as // `storebound prices ppp --update-bigmac`) // Not run in CI (network). Sources: https://data.worldbank.org/indicator/PA.NUS.PPP, // https://data.worldbank.org/indicator/PA.NUS.FCRF, https://github.com/TheEconomist/big-mac-data import { readFileSync, writeFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; import { parseArgs } from '../cli/lib/args'; import { datasetJson, datasetProblems, type PppDataset, WB, worldBankDataset } from '../cli/lib/ppp'; import { updateBigMac } from '../cli/prices-ppp'; const FILE = join(import.meta.dir, '..', 'cli', 'data', 'ppp-worldbank.json'); const a = parseArgs(process.argv.slice(2), ['check', 'bigmac']); const today = new Date().toISOString().slice(0, 10); async function json(url: string): Promise { const r = await fetch(url); if (!r.ok) throw new Error(`${url} -> ${r.status}`); return (await r.json()) as never; } if (a.has('check')) { const ds = JSON.parse(readFileSync(FILE, 'utf8')) as PppDataset; const days = Math.round((Date.parse(today) - Date.parse(ds.retrieved)) / 86_400_000); console.log(`ppp-worldbank.json: retrieved ${ds.retrieved} (${days} days ago), data up to ${ds.year}, ${Object.keys(ds.countries).length} countries${days > 365 ? ' - older than a year: run bun tools/update-ppp.ts' : ''}`); const p = datasetProblems(ds); if (p.length) { console.error(p.join('\n')); process.exit(1); } } else if (a.has('bigmac')) { await updateBigMac(resolve(a.str('project', process.cwd())), a.has('dry')); } else { const to = new Date().getFullYear(); const [ppp, fx, countries] = await Promise.all([json(WB.api(WB.ppp, 2018, to)), json(WB.api(WB.fx, 2018, to)), json(WB.countries)]); const ds = worldBankDataset(ppp, fx, countries, today); const p = datasetProblems(ds); if (p.length) throw new Error(p.join('; ')); writeFileSync(FILE, datasetJson(ds)); console.log(`wrote ${FILE}: ${Object.keys(ds.countries).length} countries, data up to ${ds.year}, retrieved ${today}`); for (const n of ds.notes ?? []) console.log(` note: ${n}`); }