Add Fedimint discovery, dual SQLite/Postgres storage, richer review handling, and generated social imagery.
57 lines
2.6 KiB
TypeScript
57 lines
2.6 KiB
TypeScript
import type { FedimintDetail, Health, MintDetail, MintListItem, Stats } from '@cashumints/shared';
|
|
|
|
/**
|
|
* Build-time API base. Islands use PUBLIC_API_BASE (see api-client.ts) so the browser
|
|
* can be pointed at a different origin than the build machine.
|
|
*/
|
|
export const API_URL = import.meta.env['API_URL'] ?? process.env['API_URL'] ?? 'http://127.0.0.1:8787';
|
|
|
|
async function get<T>(path: string): Promise<T> {
|
|
const res = await fetch(`${API_URL}${path}`, { headers: { Accept: 'application/json' } });
|
|
if (!res.ok) throw new Error(`${path} responded ${res.status}`);
|
|
return (await res.json()) as T;
|
|
}
|
|
|
|
/**
|
|
* Build-time fetches. A failure here fails the build on purpose: shipping a site with
|
|
* an empty mint list would be worse than not shipping.
|
|
*
|
|
* `fetchMints` asks for `type=cashu` rather than for everything, which is what keeps
|
|
* /mints, the mint pages, the home page grid and the sitemap's mint entries meaning
|
|
* exactly what they meant before federations were indexed. Federations are their own
|
|
* call, their own pages and their own count; nothing has to filter a mixed list and
|
|
* nothing silently grew.
|
|
*/
|
|
export const fetchMints = (): Promise<MintListItem[]> => get<MintListItem[]>('/api/mints?type=cashu');
|
|
export const fetchFedimints = (): Promise<MintListItem[]> =>
|
|
get<MintListItem[]>('/api/mints?type=fedimint');
|
|
export const fetchMint = (host: string): Promise<MintDetail> =>
|
|
get<MintDetail>(`/api/mints/${encodeURIComponent(host)}`);
|
|
/** The same endpoint, typed for a federation's flattened fields. */
|
|
export const fetchFedimint = (host: string): Promise<FedimintDetail> =>
|
|
get<FedimintDetail>(`/api/mints/${encodeURIComponent(host)}`);
|
|
export const fetchStats = (): Promise<Stats> => get<Stats>('/api/stats');
|
|
|
|
/** Health is allowed to be down at build time: the ticker just renders without it. */
|
|
export async function fetchHealth(): Promise<Health | null> {
|
|
try {
|
|
return await get<Health>('/api/health');
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Browser-facing API origin baked into the prerendered markup. Empty means same origin:
|
|
* icons resolve to /icons on whatever host serves the page, which the dev server proxy
|
|
* and the nginx config in the README both forward to the API. Never fall back to
|
|
* API_URL here — that is a build-machine address (127.0.0.1) and a visitor's browser
|
|
* cannot reach it. Set PUBLIC_API_URL only when the API lives on its own origin.
|
|
*/
|
|
export const PUBLIC_API_URL = process.env['PUBLIC_API_URL'] ?? '';
|
|
|
|
/** URL for a cached mint icon, or null. */
|
|
export function iconUrl(icon: string | null): string | null {
|
|
return icon ? `${PUBLIC_API_URL}${icon}` : null;
|
|
}
|