133 lines
3.4 KiB
TypeScript
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.id);
|
|
}
|
|
}
|