import { MultipartFile } from '@adonisjs/core/bodyparser' import { Entry, FileEntry, FolderEntry } from '#base_modules/FileManager/types/entries' import { default as EntryListService, EntryListParams, EntryListResult, } from '#base_modules/FileManager/services/entry_list_service' import createStorageService from '#base_modules/FileManager/services/storage_service/create_storage_service' import { FileStream, StorageService, } from '#base_modules/FileManager/services/storage_service/storage_service_interface' import FilePreviewService from '#base_modules/FileManager/services/file_preview_service' import EntrySearchService from '#base_modules/FileManager/services/entry_search_service' import PathService from '#base_modules/FileManager/services/path_service' import { EntryExistsException, FilenameMissingExtensionException, } from '#exceptions/file_manager_exeptions' export default class FileManagerService { private filePreviewService = new FilePreviewService() private entrySearchService = new EntrySearchService() private entryListService = new EntryListService() private pathService = new PathService() private storageService: StorageService constructor(storageService?: StorageService) { if (storageService) this.storageService = storageService else this.storageService = createStorageService() } public async listDirectory(path: string, params: EntryListParams): Promise { const entries = await this.storageService.listDirectoryEntries(path) return this.entryListService.apply(entries, params) } public async getFileEntryWithPreview(path: string): Promise { const entry = await this.storageService.getFileEntry(path) return this.filePreviewService.withPreview(entry, () => this.storageService.getFileContent(path) ) } public getFileStream(path: string): Promise { return this.storageService.getFileStream(path) } public async createDirectory(path: string, name: string): Promise { const result = await this.storageService.createDirectory(path, name) return { name, path: result.path, type: 'folder', } } public async deleteEntry(path: string): Promise { await this.storageService.deleteEntry(path) } public async moveEntry(path: string, name: string): Promise { const entry = await this.storageService.getEntry(path) const dir = this.pathService.dirname(path) const newPath = dir ? this.pathService.join(dir, name) : name if (entry.type === 'file' && !this.pathService.getFileNameMeta(name).ext) { throw new FilenameMissingExtensionException() } if (await this.storageService.entryExists(newPath)) { throw new EntryExistsException() } const result = await this.storageService.moveEntry(path, newPath) return this.storageService.getEntry(result.path) } public async writeFile(path: string, file: MultipartFile): Promise { const dir = this.pathService.toStoragePath(path) const safeName = await this.pathService.generateUniqueName(dir, file.clientName, (target) => { return this.storageService.entryExists(target) }) const writePath = this.pathService.join(dir, safeName) const result = await this.storageService.writeFile(writePath, file) return this.storageService.getEntry(result.path) } public async copyEntries(paths: string[]): Promise { const results: Entry[] = [] for (const path of paths) { try { const sourceEntry = await this.storageService.getFileEntry(path) const dir = this.pathService.dirname(sourceEntry.path) const newName = await this.pathService.generateUniqueName( dir, sourceEntry.name, (target) => this.storageService.entryExists(target), (data) => { const template = 'copy_' const regex = new RegExp(`\\s?${template}(\\d+)$`) const base = data.base.replace(regex, '').trim() return `${base} ${template}${data.count}${data.extension}` } ) const copyPath = this.pathService.join(dir, newName) const result = await this.storageService.copyEntry(path, copyPath) const copiedEntry = await this.storageService.getFileEntry(result.path) results.push(copiedEntry) } catch { continue } } return results } public async search(path: string, query: string, signal?: AbortSignal): Promise { const entries = await this.storageService.listAllEntries(path) return this.entrySearchService.search(entries, query, signal) } }