basically workable webdav

This commit is contained in:
fyears
2021-11-21 15:33:14 +08:00
parent ce0cc232c8
commit d1839706af
9 changed files with 521 additions and 192 deletions
+47 -33
View File
@@ -2,14 +2,17 @@ import { Buffer } from "buffer";
import { FileStats, Vault } from "obsidian";
import { AuthType, BufferLike, createClient } from "webdav/web";
import type { WebDAVClient, ResponseDataDetailed, FileStat } from "webdav/web";
export type { WebDAVClient } from "webdav/web";
import type { RemoteItem } from "./baseTypes";
import {
arrayBufferToBuffer,
bufferToArrayBuffer,
mkdirpInVault,
getPathFolder,
} from "./misc";
import { decryptArrayBuffer, encryptArrayBuffer } from "./encrypt";
import { fileURLToPath } from "url";
export interface WebdavConfig {
address: string;
@@ -25,6 +28,34 @@ export const DEFAULT_WEBDAV_CONFIG = {
authType: "basic",
} as WebdavConfig;
const getWebdavPath = (fileOrFolderPath: string) => {
if (!fileOrFolderPath.startsWith("/")) {
return `/${fileOrFolderPath}`;
}
return fileOrFolderPath;
};
const getNormPath = (fileOrFolderPath: string) => {
if (fileOrFolderPath.startsWith("/")) {
return fileOrFolderPath.slice(1);
}
return fileOrFolderPath;
};
const fromWebdavItemToRemoteItem = (x: FileStat) => {
let key = getNormPath(x.filename);
if (x.type === "directory" && !key.endsWith("/")) {
key = `${key}/`;
}
return {
key: key,
lastModified: Date.parse(x.lastmod).valueOf(),
size: x.size,
remoteType: "webdav",
etag: x.etag || undefined,
} as RemoteItem;
};
export const getWebdavClient = (webdavConfig: WebdavConfig) => {
if (webdavConfig.username !== "" && webdavConfig.password !== "") {
return createClient(webdavConfig.address, {
@@ -41,29 +72,14 @@ export const getWebdavClient = (webdavConfig: WebdavConfig) => {
}
};
const getWebdavPath = (fileOrFolderPath: string) => {
if (!fileOrFolderPath.startsWith("/")) {
return `/${fileOrFolderPath}`;
}
return fileOrFolderPath;
};
const getNormPath = (fileOrFolderPath: string) => {
if (fileOrFolderPath.startsWith("/")) {
return fileOrFolderPath.slice(1);
}
return fileOrFolderPath;
};
export const getRemoteMeta = async (
client: WebDAVClient,
fileOrFolderPath: string
) => {
const res = (await client.stat(getWebdavPath(fileOrFolderPath), {
details: true,
})) as ResponseDataDetailed<FileStat>;
res.data.filename = getNormPath(res.data.filename);
return res;
details: false,
})) as FileStat;
return fromWebdavItemToRemoteItem(res);
};
export const uploadToRemote = async (
@@ -88,10 +104,11 @@ export const uploadToRemote = async (
// folder
if (password === "") {
// if not encrypted, mkdir a remote folder
client.createDirectory(uploadFile, {
await client.createDirectory(uploadFile, {
recursive: true,
});
return await getRemoteMeta(client, uploadFile);
const res = await getRemoteMeta(client, uploadFile);
return res;
} else {
// if encrypted, upload a fake file with the encrypted file name
await client.putFileContents(uploadFile, "", {
@@ -111,6 +128,11 @@ export const uploadToRemote = async (
if (password !== "") {
remoteContent = await encryptArrayBuffer(localContent, password);
}
// we need to create folders before uploading
const dir = getPathFolder(uploadFile);
if (dir !== "/" && dir !== "") {
await client.createDirectory(dir, { recursive: true });
}
await client.putFileContents(uploadFile, remoteContent, {
overwrite: true,
onUploadProgress: (progress) => {
@@ -131,15 +153,12 @@ export const listFromRemote = async (client: WebDAVClient, prefix?: string) => {
details: false /* no need for verbose details here */,
glob: "/**" /* avoid dot files by using glob */,
})) as FileStat[];
for (const singleItem of contents) {
singleItem.filename = getNormPath(singleItem.filename);
}
return {
Contents: contents,
Contents: contents.map((x) => fromWebdavItemToRemoteItem(x)),
};
};
export const downloadFromRemoteRaw = async (
const downloadFromRemoteRaw = async (
client: WebDAVClient,
fileOrFolderPath: string
) => {
@@ -212,15 +231,10 @@ export const deleteFromRemote = async (
}
};
export const checkWebdavConnectivity = async (client: WebDAVClient) => {
export const checkConnectivity = async (client: WebDAVClient) => {
try {
const results = await getRemoteMeta(client, "/");
if (
results === undefined ||
results.data === undefined ||
results.data.type === undefined ||
results.data.type !== "directory"
) {
if (results === undefined) {
return false;
}
return true;