Files
warren/frontend/lib/api/warrens.ts
2025-09-06 01:21:13 +02:00

445 lines
10 KiB
TypeScript

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<Record<string, WarrenData>> {
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<string, WarrenData> = {};
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,
}),
});
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<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', 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,
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<Blob>(
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<Uint8Array> } | { success: false }
> {
if (!path.endsWith('/')) {
path += '/';
}
path += fileName;
const { data, error } = await useFetch<ReadableStream<Uint8Array>>(
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,
};
}