wulf-pulse/lib/services/datto-rmm-client-simple.ts

133 lines
3.4 KiB
TypeScript

import {
DattoRMMConfig,
DattoRMMDevice,
DattoRMMSite,
DattoRMMApiResponse,
DattoRMMError,
} from '@/lib/types/datto-rmm';
export class DattoRMMClientSimple {
private config: DattoRMMConfig;
constructor(config: DattoRMMConfig) {
this.config = config;
}
/**
* Make an API request using Basic authentication directly
*/
private async makeApiCall<T>(
endpoint: string,
options: RequestInit = {}
): Promise<T> {
// Create Basic auth header using API key and secret
const credentials = Buffer.from(`${this.config.apiKey}:${this.config.apiSecret}`).toString('base64');
// Use the base URL directly with v2 API
const url = `https://concord-api.centrastage.net/api/v2${endpoint}`;
console.log(`Making API call to: ${url}`);
const response = await fetch(url, {
...options,
headers: {
'Authorization': `Basic ${credentials}`,
'Content-Type': 'application/json',
'Accept': 'application/json',
...options.headers,
},
});
if (!response.ok) {
const errorText = await response.text();
let errorMessage = `API Error: ${response.status}`;
try {
const errorData = JSON.parse(errorText) as DattoRMMError;
errorMessage = `${errorData.error}: ${errorData.message}`;
} catch {
errorMessage += ` - ${errorText}`;
}
console.error('API call failed:', errorMessage);
throw new Error(errorMessage);
}
const responseText = await response.text();
if (!responseText) {
return {} as T;
}
try {
return JSON.parse(responseText) as T;
} catch (error) {
console.error('Failed to parse response:', responseText);
throw new Error('Invalid JSON response from API');
}
}
/**
* Get all sites
*/
async getSites(): Promise<DattoRMMSite[]> {
const response = await this.makeApiCall<DattoRMMApiResponse<DattoRMMSite>>(
'/sites',
{ method: 'GET' }
);
return response.items || [];
}
/**
* Get site by name (for matching with Autotask company)
*/
async getSiteByName(name: string): Promise<DattoRMMSite | null> {
const sites = await this.getSites();
const site = sites.find(s =>
s.name.toLowerCase() === name.toLowerCase() ||
s.name.toLowerCase().includes(name.toLowerCase())
);
return site || null;
}
/**
* Get all devices
*/
async getAllDevices(): Promise<DattoRMMDevice[]> {
const response = await this.makeApiCall<DattoRMMApiResponse<DattoRMMDevice>>(
'/devices',
{ method: 'GET' }
);
return response.items || [];
}
/**
* Get devices for a specific site
*/
async getDevicesBySite(siteId: string): Promise<DattoRMMDevice[]> {
const response = await this.makeApiCall<DattoRMMApiResponse<DattoRMMDevice>>(
`/sites/${siteId}/devices`,
{ method: 'GET' }
);
return response.items || [];
}
/**
* Get devices by site name (matches with company name)
*/
async getDevicesByCompanyName(companyName: string): Promise<DattoRMMDevice[]> {
// First, find the site that matches the company name
const site = await this.getSiteByName(companyName);
if (!site) {
console.warn(`No RMM site found for company: ${companyName}`);
return [];
}
// Then get devices for that site
return this.getDevicesBySite(site.uid);
}
}