Files
tsview/ts_web/services/api.service.ts

367 lines
10 KiB
TypeScript

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<string, number>;
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<TReq, TRes>(method: string, requestData: TReq): Promise<TRes> {
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<string[]> {
const result = await this.request<{}, { buckets: string[] }>('listBuckets', {});
return result.buckets;
}
async createBucket(bucketName: string): Promise<boolean> {
const result = await this.request<{ bucketName: string }, { success: boolean }>(
'createBucket',
{ bucketName }
);
return result.success;
}
async deleteBucket(bucketName: string): Promise<boolean> {
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<boolean> {
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<boolean> {
const result = await this.request<
{ bucketName: string; key: string },
{ success: boolean }
>('deleteObject', { bucketName, key });
return result.success;
}
async deletePrefix(bucketName: string, prefix: string): Promise<boolean> {
const result = await this.request<
{ bucketName: string; prefix: string },
{ success: boolean }
>('deletePrefix', { bucketName, prefix });
return result.success;
}
async getObjectUrl(bucketName: string, key: string): Promise<string> {
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<boolean> {
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<IMongoDatabase[]> {
const result = await this.request<{}, { databases: IMongoDatabase[] }>(
'listDatabases',
{}
);
return result.databases;
}
async createDatabase(databaseName: string): Promise<boolean> {
const result = await this.request<{ databaseName: string }, { success: boolean }>(
'createDatabase',
{ databaseName }
);
return result.success;
}
async dropDatabase(databaseName: string): Promise<boolean> {
const result = await this.request<{ databaseName: string }, { success: boolean }>(
'dropDatabase',
{ databaseName }
);
return result.success;
}
async listCollections(databaseName: string): Promise<IMongoCollection[]> {
const result = await this.request<
{ databaseName: string },
{ collections: IMongoCollection[] }
>('listCollections', { databaseName });
return result.collections;
}
async createCollection(databaseName: string, collectionName: string): Promise<boolean> {
const result = await this.request<
{ databaseName: string; collectionName: string },
{ success: boolean }
>('createCollection', { databaseName, collectionName });
return result.success;
}
async dropCollection(databaseName: string, collectionName: string): Promise<boolean> {
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<string, unknown>;
projection?: Record<string, unknown>;
sort?: Record<string, number>;
skip?: number;
limit?: number;
}
): Promise<{ documents: Record<string, unknown>[]; total: number }> {
return this.request('findDocuments', {
databaseName,
collectionName,
...options,
});
}
async getDocument(
databaseName: string,
collectionName: string,
documentId: string
): Promise<Record<string, unknown> | null> {
const result = await this.request<
{ databaseName: string; collectionName: string; documentId: string },
{ document: Record<string, unknown> | null }
>('getDocument', { databaseName, collectionName, documentId });
return result.document;
}
async insertDocument(
databaseName: string,
collectionName: string,
document: Record<string, unknown>
): Promise<string> {
const result = await this.request<
{ databaseName: string; collectionName: string; document: Record<string, unknown> },
{ insertedId: string }
>('insertDocument', { databaseName, collectionName, document });
return result.insertedId;
}
async updateDocument(
databaseName: string,
collectionName: string,
documentId: string,
update: Record<string, unknown>
): 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<string, unknown>[]
): Promise<Record<string, unknown>[]> {
const result = await this.request<
{ databaseName: string; collectionName: string; pipeline: Record<string, unknown>[] },
{ results: Record<string, unknown>[] }
>('runAggregation', { databaseName, collectionName, pipeline });
return result.results;
}
async listIndexes(
databaseName: string,
collectionName: string
): Promise<IMongoIndex[]> {
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<string, number>,
options?: { unique?: boolean; sparse?: boolean; name?: string }
): Promise<string> {
const result = await this.request<
{
databaseName: string;
collectionName: string;
keys: Record<string, number>;
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<boolean> {
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<ICollectionStats> {
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<IDatabaseStats | null> {
const result = await this.request<
{ databaseName: string },
{ stats: IDatabaseStats | null }
>('getDatabaseStats', { databaseName });
return result.stats;
}
}