import { toast } from 'vue-sonner'; import type { DirectoryEntry } from '~/types'; import type { ApiResponse } from '~/types/api'; import type { Warren } from '~/types/warrens'; import { getApiHeaders } from '.'; export async function getWarrens(): Promise> { const { data, error } = await useFetch>( 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( path: string ): Promise { // eslint-disable-next-line prefer-const let [warrenId, rest] = splitOnce(path, '/'); if (rest == null) { rest = '/'; } else { rest = '/' + decodeURI(rest); } const { data, error } = await useFetch< ApiResponse<{ files: DirectoryEntry[] }> >(getApiUrl(`warrens/files`), { method: 'POST', headers: { 'content-type': 'application/json', }, body: JSON.stringify({ warrenId, path: rest, }), }); if (data.value == null) { throw error.value?.name; } const { files } = data.value.data; return files; } export async function createDirectory( path: string, directoryName: string ): Promise<{ success: boolean }> { // eslint-disable-next-line prefer-const let [warrenId, rest] = splitOnce(path, '/'); if (rest == null) { rest = '/'; } else { rest = '/' + decodeURI(rest) + '/'; } rest += directoryName; const { status } = await useFetch(getApiUrl(`warrens/files/directory`), { method: 'POST', headers: { 'content-type': 'application/json', }, body: JSON.stringify({ warrenId, path: rest, }), }); 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 deleteWarrenDirectory( path: string, directoryName: string, force: boolean ): Promise<{ success: boolean }> { // eslint-disable-next-line prefer-const let [warrenId, rest] = splitOnce(path, '/'); if (rest == null) { rest = '/'; } else { rest = '/' + decodeURI(rest) + '/'; } rest += directoryName; const { status } = await useFetch(getApiUrl(`warrens/files/directory`), { method: 'DELETE', headers: { 'content-type': 'application/json', }, body: JSON.stringify({ warrenId, path: rest, force, }), }); const TOAST_TITLE = 'Directory'; if (status.value !== 'success') { toast.error(TOAST_TITLE, { id: 'DELETE_DIRECTORY_TOAST', description: `Failed to delete directory`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success(TOAST_TITLE, { id: 'DELETE_DIRECTORY_TOAST', description: `Successfully deleted ${directoryName}`, }); return { success: true }; } export async function deleteWarrenFile( path: string, fileName: string ): Promise<{ success: boolean }> { // eslint-disable-next-line prefer-const let [warrenId, rest] = splitOnce(path, '/'); if (rest == null) { rest = '/'; } else { rest = '/' + decodeURI(rest) + '/'; } rest += fileName; const { status } = await useFetch(getApiUrl(`warrens/files/file`), { method: 'DELETE', headers: { 'content-type': 'application/json', }, body: JSON.stringify({ warrenId, path: rest, }), }); const TOAST_TITLE = 'File'; if (status.value !== 'success') { toast.error(TOAST_TITLE, { id: 'DELETE_FILE_TOAST', description: `Failed to delete file`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success(TOAST_TITLE, { id: 'DELETE_FILE_TOAST', description: `Successfully deleted ${fileName}`, }); return { success: true }; } export async function uploadToWarren( path: string, files: FileList, onProgress: ((loaded: number, total: number) => void) | undefined ): Promise<{ success: boolean }> { // eslint-disable-next-line prefer-const let [warrenId, rest] = splitOnce(path, '/'); if (rest == null) { rest = '/'; } else { rest = '/' + decodeURI(rest); } const xhr = new XMLHttpRequest(); xhr.open('POST', getApiUrl(`warrens/files/upload`)); 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', rest); for (const file of files) { body.append('files', file); } xhr.send(body); try { await promise; } catch { toast.error('Upload', { id: 'UPLOAD_FILE_TOAST', description: `Failed to upload`, }); return { success: false }; } await refreshNuxtData('current-directory'); toast.success('Upload', { id: 'UPLOAD_FILE_TOAST', description: `Successfully uploaded ${files.length} file${files.length !== 1 ? 's' : ''}`, }); return { success: true }; } export async function renameWarrenEntry( path: string, currentName: string, newName: string ): Promise<{ success: boolean }> { // eslint-disable-next-line prefer-const let [warrenId, rest] = splitOnce(path, '/'); if (rest == null) { rest = '/'; } else { rest = '/' + decodeURI(rest) + '/'; } rest += currentName; const { status } = await useFetch(getApiUrl(`warrens/files/rename`), { method: 'PATCH', headers: { 'content-type': 'application/json', }, body: JSON.stringify({ warrenId, path: rest, newName, }), }); 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 }; }