export type UserEntry = { id: string, username: string, display_name?: string, biography?: string, joined_at?: string, age: number, // actually not just that badges?: string[] type?: 'user', karma?: number }; export type GuildEntry = { type?: 'guild', id: string, name: string, display_name?: string, description?: string, created_at?: string }; export type PostEntry = { id: string, url: string, title: string, created_at: string, author?: UserEntry | null, content?: string | null, to: UserEntry | GuildEntry }; export type ServerHealth = { version: string, name: string, post_count: number, user_count: number, me: string | null, csrf_token?: string }; export class Backend { static ENDPOINT_BASE = '/v1'; constructor () { } async fetch(url: string, options?: RequestInit) { return await fetch(`${Backend.ENDPOINT_BASE}/${url.replace(/^\/+/, '')}`, options); } withEvent(event: any) { return new EventBackend(event); } } class EventBackend extends Backend { event: any; constructor (event: any) { super(); this.event = event; } async oath (): Promise { const resp = await this.fetch("oath"); if (resp.status !== 200) { throw new Error(); } const respJ = await resp.json(); const { csrfToken } = respJ; return new CsrfEventBackend(this.event, csrfToken); } async fetch(url: string, options?: RequestInit): Promise { console.debug(`fetch ${Backend.ENDPOINT_BASE}/${url.replace(/^\/+/, '')}`); return await this.event.fetch(`${Backend.ENDPOINT_BASE}/${url.replace(/^\/+/, '')}`, options); } } class CsrfEventBackend extends EventBackend { csrfToken: string; constructor(event:EventBackend, csrfToken: string) { super(event); this.csrfToken = csrfToken; } async submitJson(url: string, data: object) { return await this.fetch(url, { method: 'POST', body: JSON.stringify(data), headers: { 'content-type': 'application/json', 'x-csrftoken': this.csrfToken } }); } } export const backend = new Backend();