import * as plugins from '../plugins.js'; // Import interfaces from shared types // Note: In bundled form these are inlined export interface IS3Object { key: string; size?: number; lastModified?: string; isPrefix?: boolean; } export interface IMongoDatabase { name: string; sizeOnDisk?: number; empty?: boolean; } export interface IMongoCollection { name: string; count?: number; } export interface IMongoIndex { name: string; keys: Record; unique?: boolean; sparse?: boolean; } export interface ICollectionStats { count: number; size: number; avgObjSize: number; storageSize: number; indexCount: number; } export interface IDatabaseStats { collections: number; views: number; objects: number; avgObjSize: number; dataSize: number; storageSize: number; indexes: number; indexSize: number; } /** * API service for communicating with the tsview backend */ export class ApiService { private baseUrl: string; constructor() { // Use current origin for API calls - TypedServer expects /typedrequest endpoint this.baseUrl = window.location.origin + '/typedrequest'; } /** * Make a typed request to the backend */ private async request(method: string, requestData: TReq): Promise { const typedRequest = new plugins.typedrequest.TypedRequest<{ method: string; request: TReq; response: TRes; }>(this.baseUrl, method); const response = await typedRequest.fire(requestData); return response; } // =========================================== // S3 API Methods // =========================================== async listBuckets(): Promise { const result = await this.request<{}, { buckets: string[] }>('listBuckets', {}); return result.buckets; } async createBucket(bucketName: string): Promise { const result = await this.request<{ bucketName: string }, { success: boolean }>( 'createBucket', { bucketName } ); return result.success; } async deleteBucket(bucketName: string): Promise { const result = await this.request<{ bucketName: string }, { success: boolean }>( 'deleteBucket', { bucketName } ); return result.success; } async listObjects( bucketName: string, prefix?: string, delimiter?: string ): Promise<{ objects: IS3Object[]; prefixes: string[] }> { return this.request('listObjects', { bucketName, prefix, delimiter }); } async getObject( bucketName: string, key: string ): Promise<{ content: string; contentType: string; size: number; lastModified: string }> { return this.request('getObject', { bucketName, key }); } async getObjectMetadata( bucketName: string, key: string ): Promise<{ contentType: string; size: number; lastModified: string }> { return this.request('getObjectMetadata', { bucketName, key }); } async putObject( bucketName: string, key: string, content: string, contentType: string ): Promise { const result = await this.request< { bucketName: string; key: string; content: string; contentType: string }, { success: boolean } >('putObject', { bucketName, key, content, contentType }); return result.success; } async deleteObject(bucketName: string, key: string): Promise { const result = await this.request< { bucketName: string; key: string }, { success: boolean } >('deleteObject', { bucketName, key }); return result.success; } async deletePrefix(bucketName: string, prefix: string): Promise { const result = await this.request< { bucketName: string; prefix: string }, { success: boolean } >('deletePrefix', { bucketName, prefix }); return result.success; } async getObjectUrl(bucketName: string, key: string): Promise { const result = await this.request< { bucketName: string; key: string }, { url: string } >('getObjectUrl', { bucketName, key }); return result.url; } async copyObject( sourceBucket: string, sourceKey: string, destBucket: string, destKey: string ): Promise { const result = await this.request< { sourceBucket: string; sourceKey: string; destBucket: string; destKey: string }, { success: boolean } >('copyObject', { sourceBucket, sourceKey, destBucket, destKey }); return result.success; } // =========================================== // MongoDB API Methods // =========================================== async listDatabases(): Promise { const result = await this.request<{}, { databases: IMongoDatabase[] }>( 'listDatabases', {} ); return result.databases; } async createDatabase(databaseName: string): Promise { const result = await this.request<{ databaseName: string }, { success: boolean }>( 'createDatabase', { databaseName } ); return result.success; } async dropDatabase(databaseName: string): Promise { const result = await this.request<{ databaseName: string }, { success: boolean }>( 'dropDatabase', { databaseName } ); return result.success; } async listCollections(databaseName: string): Promise { const result = await this.request< { databaseName: string }, { collections: IMongoCollection[] } >('listCollections', { databaseName }); return result.collections; } async createCollection(databaseName: string, collectionName: string): Promise { const result = await this.request< { databaseName: string; collectionName: string }, { success: boolean } >('createCollection', { databaseName, collectionName }); return result.success; } async dropCollection(databaseName: string, collectionName: string): Promise { const result = await this.request< { databaseName: string; collectionName: string }, { success: boolean } >('dropCollection', { databaseName, collectionName }); return result.success; } async findDocuments( databaseName: string, collectionName: string, options?: { filter?: Record; projection?: Record; sort?: Record; skip?: number; limit?: number; } ): Promise<{ documents: Record[]; total: number }> { return this.request('findDocuments', { databaseName, collectionName, ...options, }); } async getDocument( databaseName: string, collectionName: string, documentId: string ): Promise | null> { const result = await this.request< { databaseName: string; collectionName: string; documentId: string }, { document: Record | null } >('getDocument', { databaseName, collectionName, documentId }); return result.document; } async insertDocument( databaseName: string, collectionName: string, document: Record ): Promise { const result = await this.request< { databaseName: string; collectionName: string; document: Record }, { insertedId: string } >('insertDocument', { databaseName, collectionName, document }); return result.insertedId; } async updateDocument( databaseName: string, collectionName: string, documentId: string, update: Record ): Promise<{ success: boolean; modifiedCount: number }> { return this.request('updateDocument', { databaseName, collectionName, documentId, update, }); } async deleteDocument( databaseName: string, collectionName: string, documentId: string ): Promise<{ success: boolean; deletedCount: number }> { return this.request('deleteDocument', { databaseName, collectionName, documentId }); } async runAggregation( databaseName: string, collectionName: string, pipeline: Record[] ): Promise[]> { const result = await this.request< { databaseName: string; collectionName: string; pipeline: Record[] }, { results: Record[] } >('runAggregation', { databaseName, collectionName, pipeline }); return result.results; } async listIndexes( databaseName: string, collectionName: string ): Promise { const result = await this.request< { databaseName: string; collectionName: string }, { indexes: IMongoIndex[] } >('listIndexes', { databaseName, collectionName }); return result.indexes; } async createIndex( databaseName: string, collectionName: string, keys: Record, options?: { unique?: boolean; sparse?: boolean; name?: string } ): Promise { const result = await this.request< { databaseName: string; collectionName: string; keys: Record; options?: { unique?: boolean; sparse?: boolean; name?: string }; }, { indexName: string } >('createIndex', { databaseName, collectionName, keys, options }); return result.indexName; } async dropIndex( databaseName: string, collectionName: string, indexName: string ): Promise { const result = await this.request< { databaseName: string; collectionName: string; indexName: string }, { success: boolean } >('dropIndex', { databaseName, collectionName, indexName }); return result.success; } async getCollectionStats( databaseName: string, collectionName: string ): Promise { const result = await this.request< { databaseName: string; collectionName: string }, { stats: ICollectionStats } >('getCollectionStats', { databaseName, collectionName }); return result.stats; } async getServerStatus(): Promise<{ version: string; uptime: number; connections: { current: number; available: number }; }> { return this.request('getServerStatus', {}); } async getDatabaseStats(databaseName: string): Promise { const result = await this.request< { databaseName: string }, { stats: IDatabaseStats | null } >('getDatabaseStats', { databaseName }); return result.stats; } }