feat: scaffold baseos runtime
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import type { IBalenaDeviceState, IBalenaStateStatus } from './types.ts';
|
||||
|
||||
export interface ISupervisorClientOptions {
|
||||
address?: string;
|
||||
apiKey?: string;
|
||||
}
|
||||
|
||||
export class SupervisorClient {
|
||||
public readonly address?: string;
|
||||
private readonly apiKey?: string;
|
||||
|
||||
constructor(optionsArg: ISupervisorClientOptions = {}) {
|
||||
this.address = optionsArg.address || Deno.env.get('BALENA_SUPERVISOR_ADDRESS') || undefined;
|
||||
this.apiKey = optionsArg.apiKey || Deno.env.get('BALENA_SUPERVISOR_API_KEY') || undefined;
|
||||
}
|
||||
|
||||
public isConfigured() {
|
||||
return Boolean(this.address);
|
||||
}
|
||||
|
||||
public async isAvailable() {
|
||||
if (!this.address) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const response = await fetch(this.buildUrl('/ping', false));
|
||||
const text = await response.text();
|
||||
return response.ok && text.trim() === 'OK';
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async getDeviceState(): Promise<IBalenaDeviceState> {
|
||||
return await this.requestJson<IBalenaDeviceState>('/v1/device');
|
||||
}
|
||||
|
||||
public async getStateStatus(): Promise<IBalenaStateStatus> {
|
||||
return await this.requestJson<IBalenaStateStatus>('/v2/state/status');
|
||||
}
|
||||
|
||||
public async getSupervisorVersion(): Promise<string | undefined> {
|
||||
const response = await this.requestJson<{ version?: string }>('/v2/version');
|
||||
return response.version;
|
||||
}
|
||||
|
||||
public async triggerUpdate(optionsArg: { force?: boolean; cancel?: boolean } = {}) {
|
||||
await this.requestEmpty('/v1/update', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
force: Boolean(optionsArg.force),
|
||||
cancel: Boolean(optionsArg.cancel),
|
||||
}),
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public async reboot(optionsArg: { force?: boolean } = {}) {
|
||||
await this.requestEmpty('/v1/reboot', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
force: Boolean(optionsArg.force),
|
||||
}),
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private async requestJson<TResponse>(
|
||||
pathArg: string,
|
||||
initArg: RequestInit = {},
|
||||
): Promise<TResponse> {
|
||||
const response = await fetch(this.buildUrl(pathArg, true), initArg);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Supervisor request failed: ${pathArg} -> HTTP ${response.status}`);
|
||||
}
|
||||
return await response.json() as TResponse;
|
||||
}
|
||||
|
||||
private async requestEmpty(pathArg: string, initArg: RequestInit = {}) {
|
||||
const response = await fetch(this.buildUrl(pathArg, true), initArg);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Supervisor request failed: ${pathArg} -> HTTP ${response.status}`);
|
||||
}
|
||||
}
|
||||
|
||||
private buildUrl(pathArg: string, includeApiKeyArg: boolean) {
|
||||
if (!this.address) {
|
||||
throw new Error('Balena Supervisor address is not configured');
|
||||
}
|
||||
const url = new URL(pathArg, this.address.endsWith('/') ? this.address : `${this.address}/`);
|
||||
if (includeApiKeyArg) {
|
||||
if (!this.apiKey) {
|
||||
throw new Error('Balena Supervisor API key is not configured');
|
||||
}
|
||||
url.searchParams.set('apikey', this.apiKey);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user