generated from polymech/site-template
164 lines
4.4 KiB
TypeScript
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;
|
|
}
|
|
}
|
|
}
|