import type { ICheckPollResponse, IHeartbeatRequest, IResultSubmitRequest, IUptimeCheckResult, IUptimeRunnerConfig, TCheckJob, } from './interfaces.ts'; export class UptimeRunnerApiClient { private readonly instanceUrl: URL; private readonly token: string; constructor(configArg: IUptimeRunnerConfig) { this.instanceUrl = new URL(configArg.instanceUrl); this.token = configArg.token; } public async fetchAssignedChecks( runnerIdArg: string, labelsArg: string[] = [], ): Promise { const url = this.createUrl('/api/runner/v1/checks'); url.searchParams.set('runnerId', runnerIdArg); for (const label of labelsArg) { url.searchParams.append('label', label); } const responseData = await this.requestJson(url, { method: 'GET', }); if (Array.isArray(responseData)) { return responseData; } if (!Array.isArray(responseData.checks)) { throw new Error('Invalid check poll response: expected checks array.'); } return responseData.checks; } public async submitResults(runnerIdArg: string, resultsArg: IUptimeCheckResult[]): Promise { if (resultsArg.length === 0) { return; } const body: IResultSubmitRequest = { runnerId: runnerIdArg, results: resultsArg, }; await this.requestJson(this.createUrl('/api/runner/v1/results'), { method: 'POST', body: JSON.stringify(body), }); } public async heartbeat(requestArg: IHeartbeatRequest): Promise { await this.requestJson(this.createUrl('/api/runner/v1/heartbeat'), { method: 'POST', body: JSON.stringify(requestArg), }); } private createUrl(pathArg: string): URL { return new URL(pathArg, this.instanceUrl); } private async requestJson(urlArg: URL, initArg: RequestInit): Promise { const response = await fetch(urlArg, { ...initArg, headers: { accept: 'application/json', authorization: `Bearer ${this.token}`, 'content-type': 'application/json', ...(initArg.headers ?? {}), }, }); if (!response.ok) { const body = await response.text().catch(() => ''); throw new Error( `uptime.link API ${ initArg.method ?? 'GET' } ${urlArg.pathname} failed: ${response.status} ${body}`, ); } if (response.status === 204) { return undefined as T; } return await response.json() as T; } }