site-library/src/apis/filebrowser/client.ts
2025-03-08 21:04:49 +01:00

164 lines
4.4 KiB
TypeScript

import axios, { AxiosInstance } from 'axios'
import {
FileBrowserConfig,
AuthResponse,
ListingResponse,
FileOperationResponse,
} from './types.js'
import { FileCache } from './cache.js'
export class FileBrowserClient {
private client: AxiosInstance;
private cache: FileCache;
private token: string | null = null;
constructor(config: FileBrowserConfig) {
this.client = axios.create({
baseURL: config.baseUrl,
timeout: 30000, // 30 seconds
});
this.cache = new FileCache(config.cacheDuration);
// Auto login if credentials provided
if (config.username && config.password) {
this.login(config.username, config.password).catch(console.error);
}
// Add auth interceptor
this.client.interceptors.request.use(
(config) => {
if (this.token) {
config.headers.Authorization = `Bearer ${this.token}`;
}
return config;
},
(error) => Promise.reject(error)
);
}
async login(username: string, password: string): Promise<void> {
try {
const response = await this.client.post<AuthResponse>('/api/login', {
username,
password,
});
this.token = response.data.data.token;
} catch (error) {
console.error('Login failed:', error);
throw error;
}
}
async listDirectory(path: string): Promise<ListingResponse> {
// Check cache first
const cachedData = this.cache.get(path);
if (cachedData) return cachedData;
try {
const response = await this.client.get<ListingResponse>(`/api/files/list`, {
params: { path },
});
// Cache the result
this.cache.set(path, response.data);
return response.data;
} catch (error) {
console.error('Failed to list directory:', error);
throw error;
}
}
async uploadFile(file: File, destination: string): Promise<FileOperationResponse> {
const formData = new FormData();
formData.append('file', file);
try {
const response = await this.client.post<FileOperationResponse>(
'/api/files/upload',
formData,
{
params: { destination },
headers: {
'Content-Type': 'multipart/form-data',
},
}
);
// Invalidate cache for the destination directory
this.cache.remove(destination);
return response.data;
} catch (error) {
console.error('Failed to upload file:', error);
throw error;
}
}
async deleteFile(path: string): Promise<FileOperationResponse> {
try {
const response = await this.client.delete<FileOperationResponse>('/api/files', {
params: { path },
});
// Invalidate cache for the parent directory
const parentDir = path.split('/').slice(0, -1).join('/');
this.cache.remove(parentDir);
return response.data;
} catch (error) {
console.error('Failed to delete file:', error);
throw error;
}
}
async renameFile(oldPath: string, newPath: string): Promise<FileOperationResponse> {
try {
const response = await this.client.patch<FileOperationResponse>('/api/files/rename', {
old: oldPath,
new: newPath,
});
// Invalidate cache for both old and new parent directories
const oldParentDir = oldPath.split('/').slice(0, -1).join('/');
const newParentDir = newPath.split('/').slice(0, -1).join('/');
this.cache.remove(oldParentDir);
this.cache.remove(newParentDir);
return response.data;
} catch (error) {
console.error('Failed to rename file:', error);
throw error;
}
}
async createDirectory(path: string): Promise<FileOperationResponse> {
try {
const response = await this.client.post<FileOperationResponse>('/api/files/dir', {
path,
});
// Invalidate cache for the parent directory
const parentDir = path.split('/').slice(0, -1).join('/');
this.cache.remove(parentDir);
return response.data;
} catch (error) {
console.error('Failed to create directory:', error);
throw error;
}
}
async downloadFile(path: string): Promise<Blob> {
try {
const response = await this.client.get('/api/files/download', {
params: { path },
responseType: 'blob',
});
return response.data;
} catch (error) {
console.error('Failed to download file:', error);
throw error;
}
}
}