import { mkdir, stat, writeFile } from 'node:fs/promises'; import { dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { BRAND } from '../src/store/constants'; /** * Mirror the store wordmark into public/images/brand/logo_footer.png. * * Source: the logo the site publishes for its footer (BRAND.logoSourceUrl, 637×220 PNG). * The storefront ships that file instead of hotlinking la-rose.by — public/index.html * points at BRAND.logoLocalPath — and this script keeps the local copy on disk. * * Idempotent: an existing non-empty file is kept; pass `--force` to re-download it * (the source is a static theme asset, so a plain re-run is a no-op). * * pnpm fetch:logo # download only when missing * pnpm fetch:logo -- --force # refresh the local copy * * The dev server also calls `ensureBrandLogo()` once at boot (scripts/dev-server.ts), * so a fresh checkout gets the logo without an extra manual step. */ const USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36 la-rose-seed/1.0'; const REQUEST_TIMEOUT_MS = 20_000; const PUBLIC_DIR = fileURLToPath(new URL('../public', import.meta.url)); /** Absolute path of the local file served at BRAND.logoLocalPath. */ export const BRAND_LOGO_FILE = join(PUBLIC_DIR, ...BRAND.logoLocalPath.split('/').filter(Boolean)); export type BrandLogoStatus = 'kept' | 'downloaded'; /** Ensure the local logo copy is on disk; download it when missing (or when forced). */ export async function ensureBrandLogo(force = false): Promise { if (!force) { const info = await stat(BRAND_LOGO_FILE).catch(() => null); if (info && info.size > 0) return 'kept'; } const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS); try { const response = await fetch(BRAND.logoSourceUrl, { headers: { 'user-agent': USER_AGENT, accept: 'image/png,image/*;q=0.9,*/*;q=0.5' }, redirect: 'follow', signal: controller.signal, }); if (!response.ok) throw new Error(`HTTP ${response.status} ${response.statusText}`); const contentType = response.headers.get('content-type') ?? ''; if (!contentType.startsWith('image/')) { throw new Error(`unexpected content-type "${contentType || 'none'}"`); } const bytes = Buffer.from(await response.arrayBuffer()); if (bytes.length === 0) throw new Error('empty response body'); await mkdir(dirname(BRAND_LOGO_FILE), { recursive: true }); await writeFile(BRAND_LOGO_FILE, bytes); return 'downloaded'; } finally { clearTimeout(timer); } } const isDirectRun = process.argv[1] !== undefined && resolve(process.argv[1]) === fileURLToPath(import.meta.url); if (isDirectRun) { const status = await ensureBrandLogo(process.argv.includes('--force')); const kb = ((await stat(BRAND_LOGO_FILE)).size / 1024).toFixed(1); console.log( status === 'kept' ? `fetch-logo: kept ${BRAND.logoLocalPath} (${kb} kB)` : `fetch-logo: downloaded ${BRAND.logoLocalPath} (${kb} kB)`, ); }