446 lines
10 KiB
TypeScript
446 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,
|
|
}),
|
|
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<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,
|
|
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<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,
|
|
};
|
|
}
|