@multicloud-io/client
Version:
Customer-facing Multicloud API client with limited field exposure
193 lines • 7.72 kB
JavaScript
;
/**
* Multicloud API client
*
* Provides a client for customer-facing operations with limited field exposure.
* This client is designed for secure, customer-facing applications.
*
* IMPORTANT: This is for server-side use only - never expose to client/browser!
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MulticloudClient = void 0;
const https_1 = __importDefault(require("https"));
const fs_1 = __importDefault(require("fs"));
const exceptions_1 = require("./exceptions");
/**
* Multicloud API client
*
* Provides only customer-facing operations with limited field exposure.
*/
class MulticloudClient {
constructor(params, debug = false) {
this.params = params;
this.debug = debug;
}
/**
* Make an authenticated request to the Multicloud API
*/
async makeRequest(method, path, body) {
const url = `${this.params.serverUrl}${path}`;
// Build headers object
const headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
};
// Add Authorization header if accessToken is provided
if (this.params.accessToken) {
headers['Authorization'] = `Bearer ${this.params.accessToken}`;
}
else if (this.debug) {
console.log('[MulticloudClient] No accessToken provided, skipping Authorization header');
}
const options = {
method,
headers
};
// Add client certificates if provided
if (this.params.clientCert && this.params.clientKey) {
options.cert = fs_1.default.readFileSync(this.params.clientCert);
options.key = fs_1.default.readFileSync(this.params.clientKey);
}
return new Promise((resolve, reject) => {
const req = https_1.default.request(url, options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
if (this.debug) {
console.log(`[MulticloudCustomerClient] ${method} ${path} -> ${res.statusCode}`);
}
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
try {
const result = data ? JSON.parse(data) : null;
resolve(result);
}
catch (error) {
reject(new exceptions_1.MulticloudResponseError(`Failed to parse response: ${error}`));
}
}
else {
reject(new exceptions_1.MulticloudResponseError(`HTTP ${res.statusCode}: ${data}`));
}
});
});
req.on('error', (error) => {
reject(new exceptions_1.MulticloudNetworkError(`Request failed: ${error.message}`));
});
if (body) {
req.write(JSON.stringify(body));
}
req.end();
});
}
/**
* Test connection to the Multicloud server
*/
async testConnection() {
try {
await this.makeRequest('GET', '/health');
return true;
}
catch (error) {
if (this.debug) {
console.log('[MulticloudClient] Connection test failed:', error);
}
throw error;
}
}
/**
* Health check endpoint for customer API
*/
async pingCustomer() {
return this.makeRequest('GET', '/customer/ping');
}
/**
* Customer-facing endpoint to get jobs for authenticated users
*/
async getCustomerJobs(applicationId, clusterId) {
const params = new URLSearchParams();
params.append('applicationId', applicationId.toString());
if (clusterId)
params.append('clusterId', clusterId.toString());
return this.makeRequest('GET', `/customer/jobs?${params.toString()}`);
}
/**
* Customer-facing endpoint to get public games status for authenticated users
*/
async getPublicGamesStatus(applicationId, clusterId) {
const params = new URLSearchParams();
params.append('applicationId', applicationId.toString());
if (clusterId)
params.append('clusterId', clusterId.toString());
return this.makeRequest('GET', `/customer/public-game-status?${params.toString()}`);
}
/**
* Customer-facing endpoint to get clusters for authenticated users
*/
async getCustomerClusters(applicationId, clusterId) {
const params = new URLSearchParams();
params.append('applicationId', applicationId.toString());
if (clusterId)
params.append('clusterId', clusterId.toString());
return this.makeRequest('GET', `/customer/clusters?${params.toString()}`);
}
/**
* Customer-facing endpoint to get basic server information for authenticated users
*/
async getCustomerServers(applicationId, clusterId) {
const params = new URLSearchParams();
params.append('applicationId', applicationId.toString());
if (clusterId)
params.append('clusterId', clusterId.toString());
return this.makeRequest('GET', `/customer/servers?${params.toString()}`);
}
/**
* Customer-facing endpoint to get tasks for authenticated users
*/
async getCustomerTasks(applicationId, jobIds, clusterId) {
const params = new URLSearchParams();
params.append('applicationId', applicationId.toString());
if (jobIds && jobIds.size > 0) {
jobIds.forEach(jobId => params.append('jobIds', jobId.toString()));
}
if (clusterId)
params.append('clusterId', clusterId.toString());
return this.makeRequest('GET', `/customer/tasks?${params.toString()}`);
}
/**
* Customer-facing endpoint to get cluster locations (different from admin endpoint)
*/
async getCustomerClusterLocations(applicationId, clusterId) {
const params = new URLSearchParams();
params.append('applicationId', applicationId.toString());
params.append('clusterId', clusterId.toString());
return this.makeRequest('GET', `/customer/locations?${params.toString()}`);
}
/**
* Customer-facing endpoint to add jobs to a cluster (different from coordinator endpoint)
*/
async addCustomerJobs(jobDescs, applicationId, clusterId) {
const params = new URLSearchParams();
params.append('applicationId', applicationId.toString());
params.append('clusterId', clusterId.toString());
return this.makeRequest('POST', `/customer/jobs?${params.toString()}`, jobDescs);
}
/**
* Customer-facing endpoint to perform job actions (different from coordinator endpoint)
*/
async customerJobAction(jobId, action, applicationId, clusterId, scaleBy) {
const params = new URLSearchParams();
params.append('action', action);
params.append('applicationId', applicationId.toString());
params.append('clusterId', clusterId.toString());
if (scaleBy !== undefined)
params.append('by', scaleBy.toString());
return this.makeRequest('PUT', `/customer/job/${jobId}?${params.toString()}`);
}
}
exports.MulticloudClient = MulticloudClient;
//# sourceMappingURL=multicloud-client.js.map