the most notable improvement is that uploads are now using streams so they no longer require the entire file to be stored in memory
303 lines
7.1 KiB
TypeScript
303 lines
7.1 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<DirectoryEntry[]> {
|
|
const { data, error } = await useFetch<
|
|
ApiResponse<{ files: DirectoryEntry[] }>
|
|
>(getApiUrl(`warrens/files/ls`), {
|
|
method: 'POST',
|
|
headers: getApiHeaders(),
|
|
body: JSON.stringify({
|
|
warrenId,
|
|
path,
|
|
}),
|
|
});
|
|
|
|
if (data.value == null) {
|
|
throw error.value?.name;
|
|
}
|
|
|
|
const { files } = data.value.data;
|
|
|
|
return files;
|
|
}
|
|
|
|
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 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,
|
|
path,
|
|
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(
|
|
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,
|
|
path,
|
|
force: false,
|
|
}),
|
|
});
|
|
|
|
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(
|
|
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 {
|
|
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(
|
|
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 }> {
|
|
if (!path.endsWith('/')) {
|
|
path += '/';
|
|
}
|
|
path += fileName;
|
|
|
|
const { data, error } = await useFetch<Blob>(
|
|
getApiUrl(`warrens/files/cat?warrenId=${warrenId}&path=${path}`),
|
|
{
|
|
method: 'GET',
|
|
headers: getApiHeaders(),
|
|
responseType: 'blob',
|
|
cache: 'default',
|
|
}
|
|
);
|
|
|
|
if (data.value == null || error.value != null) {
|
|
return {
|
|
success: false,
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
data: data.value,
|
|
};
|
|
}
|