import { toast } from 'vue-sonner'; import type { DirectoryEntry } from '#shared/types'; import type { ApiResponse } from '#shared/types/api'; import type { WarrenData } from '#shared/types/warrens'; import { getApiHeaders, getAuthHeader } from '.'; export async function getWarrens(): Promise> { const { data, error } = await useFetch< ApiResponse<{ warrens: WarrenData[] }> >(getApiUrl('warrens'), { method: 'GET', headers: getApiHeaders(), }); if (data.value == null) { throw error.value?.name; } const warrens: Record = {}; for (const warren of data.value.data.warrens) { warrens[warren.id] = warren; } return warrens; } export async function getWarrenDirectory( warrenId: string, path: string ): Promise<{ files: DirectoryEntry[]; parent: DirectoryEntry | null }> { const { data, error } = await useFetch< ApiResponse<{ files: DirectoryEntry[]; parent: DirectoryEntry | null }> >(getApiUrl(`warrens/files/ls`), { method: 'POST', headers: getApiHeaders(), body: JSON.stringify({ warrenId, path, }), key: `${warrenId}-${path}`, }); if (data.value == null) { throw error.value?.name; } const { files, parent } = data.value.data; return { files, parent }; } export async function createDirectory( warrenId: string, path: string, directoryName: string ): Promise<{ success: boolean }> { if (!path.endsWith('/')) { path += '/'; } path += directoryName; const { status } = await useFetch(getApiUrl(`warrens/files/mkdir`), { method: 'POST', headers: getApiHeaders(), body: JSON.stringify({ warrenId, path, }), }); if (status.value !== 'success') { toast.error('Directory', { id: 'CREATE_DIRECTORY_TOAST', description: `Failed to create directory`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success('Directory', { id: 'CREATE_DIRECTORY_TOAST', description: `Successfully created directory: ${directoryName}`, }); return { success: true }; } export async function warrenRm( warrenId: string, paths: string[], force: boolean ): Promise<{ success: boolean }> { const { status } = await useFetch(getApiUrl(`warrens/files/rm`), { method: 'POST', headers: getApiHeaders(), body: JSON.stringify({ warrenId, paths, force, }), }); const TOAST_TITLE = 'Delete'; if (status.value !== 'success') { toast.error(TOAST_TITLE, { id: 'WARREN_RM_TOAST', description: `Failed to delete directory`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success(TOAST_TITLE, { id: 'WARREN_RM_TOAST', description: `Successfully deleted files`, }); return { success: true }; } export async function deleteWarrenDirectory( warrenId: string, path: string, directoryName: string, force: boolean ): Promise<{ success: boolean }> { if (!path.endsWith('/')) { path += '/'; } path += directoryName; const { status } = await useFetch(getApiUrl(`warrens/files/rm`), { method: 'POST', headers: getApiHeaders(), body: JSON.stringify({ warrenId, paths: [path], force, }), }); const TOAST_TITLE = 'Directory'; if (status.value !== 'success') { toast.error(TOAST_TITLE, { id: 'WARREN_RM_TOAST', description: `Failed to delete directory`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success(TOAST_TITLE, { id: 'WARREN_RM_TOAST', description: `Successfully deleted ${directoryName}`, }); return { success: true }; } export async function deleteWarrenFile( warrenId: string, path: string, fileName: string ): Promise<{ success: boolean }> { if (!path.endsWith('/')) { path += '/'; } path += fileName; const { status } = await useFetch(getApiUrl(`warrens/files/rm`), { method: 'POST', headers: getApiHeaders(), body: JSON.stringify({ warrenId, paths: [path], force: false, }), }); const TOAST_TITLE = 'File'; if (status.value !== 'success') { toast.error(TOAST_TITLE, { id: 'WARREN_RM_TOAST', description: `Failed to delete file`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success(TOAST_TITLE, { id: 'WARREN_RM_TOAST', description: `Successfully deleted ${fileName}`, }); return { success: true }; } export async function uploadToWarren( warrenId: string, path: string, files: FileList, onProgress: ((loaded: number, total: number) => void) | undefined ): Promise<{ success: boolean }> { const xhr = new XMLHttpRequest(); xhr.open('POST', getApiUrl(`warrens/files/save`)); xhr.upload.onprogress = (e) => { onProgress?.(e.loaded, e.total); }; const promise = new Promise((res, rej) => { xhr.onreadystatechange = (_) => { if (xhr.readyState !== 4) { return; } if (xhr.status >= 200 && xhr.status <= 300) { res(); } else { rej(); } }; }); const body = new FormData(); body.set('warrenId', warrenId); body.set('path', path); for (const file of files) { body.append('files', file); } const header = getAuthHeader(); if (header != null) { xhr.setRequestHeader(header[0], header[1]); } xhr.send(body); try { await promise; } catch { return { success: false }; } await refreshNuxtData('current-directory'); return { success: true }; } export async function renameWarrenEntry( warrenId: string, path: string, currentName: string, newName: string ): Promise<{ success: boolean }> { if (!path.endsWith('/')) { path += '/'; } let targetPath = path; targetPath += newName; path += currentName; const { status } = await useFetch(getApiUrl(`warrens/files/mv`), { method: 'POST', headers: getApiHeaders(), body: JSON.stringify({ warrenId, paths: [path], targetPath, }), }); if (status.value !== 'success') { toast.error('Rename', { id: 'RENAME_FILE_TOAST', description: `Failed to rename ${currentName}`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success('Rename', { id: 'RENAME_FILE_TOAST', description: `Successfully renamed ${currentName} to ${newName}`, }); return { success: true }; } export async function fetchFile( warrenId: string, path: string, fileName: string ): Promise<{ success: true; data: Blob } | { success: false }> { return fetchFiles(warrenId, path, [fileName]); } export async function fetchFiles( warrenId: string, path: string, fileNames: string[] ): Promise<{ success: true; data: Blob } | { success: false }> { if (!path.endsWith('/')) { path += '/'; } const paths = []; for (const fileName of fileNames) { paths.push(path + fileName); } const { data, error } = await useFetch( getApiUrl( `warrens/files/cat?warrenId=${warrenId}&paths=${paths.join(':')}` ), { method: 'GET', headers: getApiHeaders(), responseType: 'blob', cache: 'default', } ); if (data.value == null || error.value != null) { return { success: false, }; } return { success: true, data: data.value, }; } export async function fetchFileStream( warrenId: string, path: string, fileName: string ): Promise< { success: true; stream: ReadableStream } | { success: false } > { if (!path.endsWith('/')) { path += '/'; } path += fileName; const { data, error } = await useFetch>( getApiUrl(`warrens/files/cat?warrenId=${warrenId}&paths=${path}`), { method: 'GET', headers: getApiHeaders(), responseType: 'stream', cache: 'default', } ); if (data.value == null || error.value != null) { return { success: false, }; } return { success: true, stream: data.value, }; } export async function moveFiles( warrenId: string, currentPaths: string[], targetPath: string ): Promise<{ success: boolean }> { const { status } = await useFetch(getApiUrl(`warrens/files/mv`), { method: 'POST', headers: getApiHeaders(), body: JSON.stringify({ warrenId, paths: currentPaths, targetPath: targetPath, }), }); if (status.value !== 'success') { toast.error('Move', { id: 'MOVE_FILE_TOAST', description: `Failed to move file`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success('Rename', { id: 'MOVE_FILE_TOAST', description: `Successfully moved file`, }); return { success: true, }; } export async function copyFile( warrenId: string, currentPath: string, targetPath: string ): Promise<{ success: boolean }> { const { status } = await useFetch(getApiUrl(`warrens/files/cp`), { method: 'POST', headers: getApiHeaders(), body: JSON.stringify({ warrenId, path: currentPath, targetPath: targetPath, }), }); if (status.value !== 'success') { toast.error('Copy', { id: 'COPY_FILE_TOAST', description: `Failed to copy file`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success('Copy', { id: 'COPY_FILE_TOAST', description: `Successfully copied file`, }); return { success: true, }; }