UNPKG

niledatabase

Version:

Command line interface for Nile databases

202 lines (201 loc) 8.63 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.NileAPI = void 0; const axios_1 = __importDefault(require("axios")); const colors_1 = require("./colors"); class NileAPI { constructor(options) { this.debug = options.debug || false; if (!options.token) { throw new Error('Token is required'); } this.token = options.token; // Handle URL override if (options.controlPlaneUrl) { // Remove any protocol prefix if present this.controlPlaneUrl = options.controlPlaneUrl.replace(/^(https?:\/\/)/, ''); // Add https:// prefix this.controlPlaneUrl = `https://${this.controlPlaneUrl}`; } else { this.controlPlaneUrl = NileAPI.DEFAULT_CONTROL_PLANE_URL; } // Set user URL this.userUrl = NileAPI.DEFAULT_USER_URL; if (this.debug) { console.log(colors_1.theme.dim('\nAPI Configuration:')); console.log(colors_1.theme.dim('Control Plane URL:'), this.controlPlaneUrl); console.log(colors_1.theme.dim('User API URL:'), this.userUrl); console.log(); } // Create control plane client for workspace/database operations this.controlPlaneClient = axios_1.default.create({ baseURL: this.controlPlaneUrl, headers: { Authorization: `Bearer ${this.token}`, 'Content-Type': 'application/json' }, }); // Create user client for user operations this.userClient = axios_1.default.create({ baseURL: this.userUrl, headers: { Authorization: `Bearer ${this.token}`, 'Content-Type': 'application/json' }, }); // Add debug logging this.addDebugLogging(this.controlPlaneClient); this.addDebugLogging(this.userClient); this.dbHost = options.dbHost; } addDebugLogging(client) { client.interceptors.request.use(request => { if (this.debug) { console.log(colors_1.theme.dim('\nAPI Request:')); console.log(colors_1.theme.dim(`${request.method?.toUpperCase()} ${request.baseURL}${request.url}`)); console.log(colors_1.theme.dim('Headers:'), { ...request.headers, Authorization: request.headers.Authorization ? 'Bearer [hidden]' : undefined }); if (request.data) { console.log(colors_1.theme.dim('Body:'), request.data); } console.log(); } return request; }); client.interceptors.response.use(response => { if (this.debug) { console.log(colors_1.theme.dim('API Response Status:'), response.status); if (response.data) { console.log(colors_1.theme.dim('Response Data:'), response.data); } } return response; }, error => { if (this.debug && error.response) { console.log(colors_1.theme.dim('API Error Response:'), { status: error.response.status, data: error.response.data }); } throw error; }); } async getDatabaseConnection(workspaceSlug, databaseName) { // Get database credentials from control plane if (this.debug) { console.log(colors_1.theme.dim('\nFetching database credentials...')); } const credentials = await this.createDatabaseCredentials(workspaceSlug, databaseName); if (!credentials.id || !credentials.password) { throw new Error('Invalid credentials received from server'); } // Get the region from the database info const region = credentials.database.region; // e.g., AWS_US_WEST_2 or AZURE_EASTUS const regionParts = region.toLowerCase().split('_'); const cloudProvider = regionParts[0]; // aws or azure const regionId = regionParts.slice(1).join('-'); // e.g., us-west-2 or eastus // Use custom host if provided, otherwise construct based on cloud provider let dbHost; if (cloudProvider === 'azure') { dbHost = `db.${regionId}.azure.thenile.dev`; } else { // Default AWS format dbHost = `${regionId}.db.thenile.dev`; } if (this.debug) { console.log(colors_1.theme.dim('\nPostgreSQL Connection Details:')); console.log(colors_1.theme.dim('Cloud Provider:'), cloudProvider); console.log(colors_1.theme.dim('Region:'), regionId); console.log(colors_1.theme.dim('Host:'), dbHost); console.log(colors_1.theme.dim('Database:'), databaseName); console.log(colors_1.theme.dim('User:'), credentials.id); console.log(); } return { host: dbHost, database: databaseName, user: credentials.id, password: credentials.password, port: 5432 }; } async getDeveloperInfo() { const response = await this.controlPlaneClient.get('/developers/me'); return response.data; } async listDatabases(workspaceSlug) { const response = await this.controlPlaneClient.get(`/workspaces/${workspaceSlug}/databases`); return response.data; } async createDatabase(workspaceSlug, name, region) { const response = await this.controlPlaneClient.post(`/workspaces/${workspaceSlug}/databases`, { databaseName: name, region, }); return response.data; } async getDatabase(workspaceSlug, databaseName) { const response = await this.controlPlaneClient.get(`/workspaces/${workspaceSlug}/databases/${databaseName}`); return response.data; } async deleteDatabase(workspaceSlug, databaseName) { await this.controlPlaneClient.delete(`/workspaces/${workspaceSlug}/databases/${databaseName}`); } async listDatabaseCredentials(workspaceSlug, databaseName) { const response = await this.controlPlaneClient.get(`/workspaces/${workspaceSlug}/databases/${databaseName}/credentials`); return response.data; } async createDatabaseCredentials(workspaceSlug, databaseName) { const response = await this.controlPlaneClient.post(`/workspaces/${workspaceSlug}/databases/${databaseName}/credentials`); return response.data; } async listRegions(workspaceSlug) { const response = await this.controlPlaneClient.get(`/workspaces/${workspaceSlug}/regions`); return response.data; } async listWorkspaces() { const response = await this.controlPlaneClient.get('/workspaces'); return response.data; } async getWorkspace(workspaceSlug) { const response = await this.controlPlaneClient.get(`/workspaces/${workspaceSlug}`); return response.data; } async getDatabaseId(workspaceSlug, databaseName) { const database = await this.getDatabase(workspaceSlug, databaseName); if (!database.id) { throw new Error(`Could not find database ID for database '${databaseName}'`); } return database.id; } async createUser(databaseId, user, options) { const response = await this.userClient.post(`/v2/databases/${databaseId}/users`, user, { params: { tenantId: options?.tenantId, newTenantName: options?.newTenantName } }); return response.data; } async getUserTenants(databaseId, userId) { const response = await this.userClient.get(`/v2/databases/${databaseId}/users/${userId}/tenants`); return response.data; } async updateUser(databaseId, userId, updates) { const response = await this.userClient.patch(`/v2/databases/${databaseId}/users/${userId}`, updates); return response.data; } async removeUserFromTenant(databaseId, userId, tenantId) { await this.userClient.delete(`/v2/databases/${databaseId}/users/${userId}/tenants/${tenantId}`); } } exports.NileAPI = NileAPI; NileAPI.DEFAULT_CONTROL_PLANE_URL = 'https://global.thenile.dev'; NileAPI.DEFAULT_USER_URL = 'https://us-west-2.api.thenile.dev';