Files
warren/frontend/lib/api/warrens.ts
2025-07-15 06:14:57 +02:00

258 lines
6.1 KiB
TypeScript

import { toast } from 'vue-sonner';
import type { DirectoryEntry, FileType } from '~/types';
import type { ApiResponse } from '~/types/api';
import type { Warren } from '~/types/warrens';
export async function getWarrens(): Promise<Record<string, Warren>> {
const { data, error } = await useFetch<ApiResponse<{ warrens: Warren[] }>>(
getApiUrl('warrens'),
{
method: 'GET',
}
);
if (data.value == null) {
throw error.value?.name;
}
const warrens: Record<string, Warren> = {};
for (const warren of data.value.data.warrens) {
warrens[warren.id] = warren;
}
return warrens;
}
export async function getWarrenDirectory(
path: string
): Promise<DirectoryEntry[]> {
// 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 = '/' + 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
): Promise<{ success: boolean }> {
// eslint-disable-next-line prefer-const
let [warrenId, rest] = splitOnce(path, '/');
if (rest == null) {
rest = '/';
} else {
rest = '/' + 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: false,
}),
});
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 = '/' + 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 = '/' + 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<void>((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 };
}