webdav also sync in vault folder
This commit is contained in:
parent
437e041e71
commit
44480be707
@ -834,7 +834,9 @@ class RemotelySaveSettingTab extends PluginSettingTab {
|
|||||||
const client = new RemoteClient(
|
const client = new RemoteClient(
|
||||||
"webdav",
|
"webdav",
|
||||||
undefined,
|
undefined,
|
||||||
this.plugin.settings.webdav
|
this.plugin.settings.webdav,
|
||||||
|
undefined,
|
||||||
|
this.app.vault.getName()
|
||||||
);
|
);
|
||||||
const res = await client.checkConnectivity();
|
const res = await client.checkConnectivity();
|
||||||
if (res) {
|
if (res) {
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export class RemoteClient {
|
|||||||
readonly serviceType: SUPPORTED_SERVICES_TYPE;
|
readonly serviceType: SUPPORTED_SERVICES_TYPE;
|
||||||
readonly s3Client?: s3.S3Client;
|
readonly s3Client?: s3.S3Client;
|
||||||
readonly s3Config?: S3Config;
|
readonly s3Config?: S3Config;
|
||||||
readonly webdavClient?: webdav.WebDAVClient;
|
readonly webdavClient?: webdav.WrappedWebdavClient;
|
||||||
readonly webdavConfig?: WebdavConfig;
|
readonly webdavConfig?: WebdavConfig;
|
||||||
readonly dropboxClient?: dropbox.WrappedDropboxClient;
|
readonly dropboxClient?: dropbox.WrappedDropboxClient;
|
||||||
readonly dropboxConfig?: DropboxConfig;
|
readonly dropboxConfig?: DropboxConfig;
|
||||||
@ -34,8 +34,11 @@ export class RemoteClient {
|
|||||||
this.s3Config = s3Config;
|
this.s3Config = s3Config;
|
||||||
this.s3Client = s3.getS3Client(this.s3Config);
|
this.s3Client = s3.getS3Client(this.s3Config);
|
||||||
} else if (serviceType === "webdav") {
|
} else if (serviceType === "webdav") {
|
||||||
|
if (vaultName === undefined) {
|
||||||
|
throw Error("remember to provide vault name while init webdav client");
|
||||||
|
}
|
||||||
this.webdavConfig = webdavConfig;
|
this.webdavConfig = webdavConfig;
|
||||||
this.webdavClient = webdav.getWebdavClient(this.webdavConfig);
|
this.webdavClient = webdav.getWebdavClient(this.webdavConfig, vaultName);
|
||||||
} else if (serviceType === "dropbox") {
|
} else if (serviceType === "dropbox") {
|
||||||
if (vaultName === undefined || saveUpdatedConfigFunc === undefined) {
|
if (vaultName === undefined || saveUpdatedConfigFunc === undefined) {
|
||||||
throw Error(
|
throw Error(
|
||||||
|
|||||||
@ -21,22 +21,35 @@ export const DEFAULT_WEBDAV_CONFIG = {
|
|||||||
authType: "basic",
|
authType: "basic",
|
||||||
} as WebdavConfig;
|
} as WebdavConfig;
|
||||||
|
|
||||||
const getWebdavPath = (fileOrFolderPath: string) => {
|
const getWebdavPath = (fileOrFolderPath: string, vaultName: string) => {
|
||||||
|
let key = fileOrFolderPath;
|
||||||
|
if (fileOrFolderPath === "/" || fileOrFolderPath === "") {
|
||||||
|
// special
|
||||||
|
key = `/${vaultName}/`;
|
||||||
|
}
|
||||||
if (!fileOrFolderPath.startsWith("/")) {
|
if (!fileOrFolderPath.startsWith("/")) {
|
||||||
return `/${fileOrFolderPath}`;
|
key = `/${vaultName}/${fileOrFolderPath}`;
|
||||||
}
|
}
|
||||||
return fileOrFolderPath;
|
return key;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getNormPath = (fileOrFolderPath: string) => {
|
const getNormPath = (fileOrFolderPath: string, vaultName: string) => {
|
||||||
if (fileOrFolderPath.startsWith("/")) {
|
if (
|
||||||
return fileOrFolderPath.slice(1);
|
!(
|
||||||
|
fileOrFolderPath === `/${vaultName}` ||
|
||||||
|
fileOrFolderPath.startsWith(`/${vaultName}/`)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw Error(`"${fileOrFolderPath}" doesn't starts with "/${vaultName}/"`);
|
||||||
}
|
}
|
||||||
return fileOrFolderPath;
|
// if (fileOrFolderPath.startsWith("/")) {
|
||||||
|
// return fileOrFolderPath.slice(1);
|
||||||
|
// }
|
||||||
|
return fileOrFolderPath.slice(`/${vaultName}/`.length);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fromWebdavItemToRemoteItem = (x: FileStat) => {
|
const fromWebdavItemToRemoteItem = (x: FileStat, vaultName: string) => {
|
||||||
let key = getNormPath(x.filename);
|
let key = getNormPath(x.filename, vaultName);
|
||||||
if (x.type === "directory" && !key.endsWith("/")) {
|
if (x.type === "directory" && !key.endsWith("/")) {
|
||||||
key = `${key}/`;
|
key = `${key}/`;
|
||||||
}
|
}
|
||||||
@ -49,45 +62,90 @@ const fromWebdavItemToRemoteItem = (x: FileStat) => {
|
|||||||
} as RemoteItem;
|
} as RemoteItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getWebdavClient = (webdavConfig: WebdavConfig) => {
|
export class WrappedWebdavClient {
|
||||||
if (webdavConfig.username !== "" && webdavConfig.password !== "") {
|
webdavConfig: WebdavConfig;
|
||||||
return createClient(webdavConfig.address, {
|
vaultName: string;
|
||||||
username: webdavConfig.username,
|
client: WebDAVClient;
|
||||||
password: webdavConfig.password,
|
vaultFolderExists: boolean;
|
||||||
|
constructor(webdavConfig: WebdavConfig, vaultName: string) {
|
||||||
|
this.webdavConfig = webdavConfig;
|
||||||
|
this.vaultName = vaultName;
|
||||||
|
this.vaultFolderExists = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
init = async () => {
|
||||||
|
// init client if not inited
|
||||||
|
if (this.client === undefined) {
|
||||||
|
if (
|
||||||
|
this.webdavConfig.username !== "" &&
|
||||||
|
this.webdavConfig.password !== ""
|
||||||
|
) {
|
||||||
|
this.client = createClient(this.webdavConfig.address, {
|
||||||
|
username: this.webdavConfig.username,
|
||||||
|
password: this.webdavConfig.password,
|
||||||
authType:
|
authType:
|
||||||
webdavConfig.authType === "digest"
|
this.webdavConfig.authType === "digest"
|
||||||
? AuthType.Digest
|
? AuthType.Digest
|
||||||
: AuthType.Password,
|
: AuthType.Password,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log("no password");
|
console.log("no password");
|
||||||
return createClient(webdavConfig.address);
|
this.client = createClient(this.webdavConfig.address);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check vault folder
|
||||||
|
if (this.vaultFolderExists) {
|
||||||
|
// pass
|
||||||
|
} else {
|
||||||
|
const res = await this.client.exists(`/${this.vaultName}`);
|
||||||
|
if (res) {
|
||||||
|
console.log("exits!");
|
||||||
|
this.vaultFolderExists = true;
|
||||||
|
} else {
|
||||||
|
console.log("not exists, creating");
|
||||||
|
await this.client.createDirectory(`/${this.vaultName}`);
|
||||||
|
console.log("created!");
|
||||||
|
this.vaultFolderExists = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getWebdavClient = (
|
||||||
|
webdavConfig: WebdavConfig,
|
||||||
|
vaultName: string
|
||||||
|
) => {
|
||||||
|
return new WrappedWebdavClient(webdavConfig, vaultName);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getRemoteMeta = async (
|
export const getRemoteMeta = async (
|
||||||
client: WebDAVClient,
|
client: WrappedWebdavClient,
|
||||||
fileOrFolderPath: string
|
fileOrFolderPath: string
|
||||||
) => {
|
) => {
|
||||||
const res = (await client.stat(getWebdavPath(fileOrFolderPath), {
|
await client.init();
|
||||||
|
const remotePath = getWebdavPath(fileOrFolderPath, client.vaultName);
|
||||||
|
console.log(`remotePath = ${remotePath}`);
|
||||||
|
const res = (await client.client.stat(remotePath, {
|
||||||
details: false,
|
details: false,
|
||||||
})) as FileStat;
|
})) as FileStat;
|
||||||
return fromWebdavItemToRemoteItem(res);
|
return fromWebdavItemToRemoteItem(res, client.vaultName);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const uploadToRemote = async (
|
export const uploadToRemote = async (
|
||||||
client: WebDAVClient,
|
client: WrappedWebdavClient,
|
||||||
fileOrFolderPath: string,
|
fileOrFolderPath: string,
|
||||||
vault: Vault,
|
vault: Vault,
|
||||||
isRecursively: boolean = false,
|
isRecursively: boolean = false,
|
||||||
password: string = "",
|
password: string = "",
|
||||||
remoteEncryptedKey: string = ""
|
remoteEncryptedKey: string = ""
|
||||||
) => {
|
) => {
|
||||||
|
await client.init();
|
||||||
let uploadFile = fileOrFolderPath;
|
let uploadFile = fileOrFolderPath;
|
||||||
if (password !== "") {
|
if (password !== "") {
|
||||||
uploadFile = remoteEncryptedKey;
|
uploadFile = remoteEncryptedKey;
|
||||||
}
|
}
|
||||||
uploadFile = getWebdavPath(uploadFile);
|
uploadFile = getWebdavPath(uploadFile, client.vaultName);
|
||||||
|
|
||||||
const isFolder = fileOrFolderPath.endsWith("/");
|
const isFolder = fileOrFolderPath.endsWith("/");
|
||||||
|
|
||||||
@ -97,14 +155,14 @@ export const uploadToRemote = async (
|
|||||||
// folder
|
// folder
|
||||||
if (password === "") {
|
if (password === "") {
|
||||||
// if not encrypted, mkdir a remote folder
|
// if not encrypted, mkdir a remote folder
|
||||||
await client.createDirectory(uploadFile, {
|
await client.client.createDirectory(uploadFile, {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
});
|
});
|
||||||
const res = await getRemoteMeta(client, uploadFile);
|
const res = await getRemoteMeta(client, uploadFile);
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
// if encrypted, upload a fake file with the encrypted file name
|
// if encrypted, upload a fake file with the encrypted file name
|
||||||
await client.putFileContents(uploadFile, "", {
|
await client.client.putFileContents(uploadFile, "", {
|
||||||
overwrite: true,
|
overwrite: true,
|
||||||
onUploadProgress: (progress) => {
|
onUploadProgress: (progress) => {
|
||||||
console.log(`Uploaded ${progress.loaded} bytes of ${progress.total}`);
|
console.log(`Uploaded ${progress.loaded} bytes of ${progress.total}`);
|
||||||
@ -124,9 +182,9 @@ export const uploadToRemote = async (
|
|||||||
// we need to create folders before uploading
|
// we need to create folders before uploading
|
||||||
const dir = getPathFolder(uploadFile);
|
const dir = getPathFolder(uploadFile);
|
||||||
if (dir !== "/" && dir !== "") {
|
if (dir !== "/" && dir !== "") {
|
||||||
await client.createDirectory(dir, { recursive: true });
|
await client.client.createDirectory(dir, { recursive: true });
|
||||||
}
|
}
|
||||||
await client.putFileContents(uploadFile, remoteContent, {
|
await client.client.putFileContents(uploadFile, remoteContent, {
|
||||||
overwrite: true,
|
overwrite: true,
|
||||||
onUploadProgress: (progress) => {
|
onUploadProgress: (progress) => {
|
||||||
console.log(`Uploaded ${progress.loaded} bytes of ${progress.total}`);
|
console.log(`Uploaded ${progress.loaded} bytes of ${progress.total}`);
|
||||||
@ -137,26 +195,36 @@ export const uploadToRemote = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const listFromRemote = async (client: WebDAVClient, prefix?: string) => {
|
export const listFromRemote = async (
|
||||||
|
client: WrappedWebdavClient,
|
||||||
|
prefix?: string
|
||||||
|
) => {
|
||||||
if (prefix !== undefined) {
|
if (prefix !== undefined) {
|
||||||
throw Error("prefix not supported");
|
throw Error("prefix not supported");
|
||||||
}
|
}
|
||||||
const contents = (await client.getDirectoryContents("/", {
|
await client.init();
|
||||||
|
const contents = (await client.client.getDirectoryContents(
|
||||||
|
`/${client.vaultName}`,
|
||||||
|
{
|
||||||
deep: true,
|
deep: true,
|
||||||
details: false /* no need for verbose details here */,
|
details: false /* no need for verbose details here */,
|
||||||
glob: "/**" /* avoid dot files by using glob */,
|
glob: "/**" /* avoid dot files by using glob */,
|
||||||
})) as FileStat[];
|
}
|
||||||
|
)) as FileStat[];
|
||||||
return {
|
return {
|
||||||
Contents: contents.map((x) => fromWebdavItemToRemoteItem(x)),
|
Contents: contents.map((x) =>
|
||||||
|
fromWebdavItemToRemoteItem(x, client.vaultName)
|
||||||
|
),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadFromRemoteRaw = async (
|
const downloadFromRemoteRaw = async (
|
||||||
client: WebDAVClient,
|
client: WrappedWebdavClient,
|
||||||
fileOrFolderPath: string
|
fileOrFolderPath: string
|
||||||
) => {
|
) => {
|
||||||
const buff = (await client.getFileContents(
|
await client.init();
|
||||||
getWebdavPath(fileOrFolderPath)
|
const buff = (await client.client.getFileContents(
|
||||||
|
getWebdavPath(fileOrFolderPath, client.vaultName)
|
||||||
)) as BufferLike;
|
)) as BufferLike;
|
||||||
if (buff instanceof ArrayBuffer) {
|
if (buff instanceof ArrayBuffer) {
|
||||||
return buff;
|
return buff;
|
||||||
@ -167,13 +235,15 @@ const downloadFromRemoteRaw = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const downloadFromRemote = async (
|
export const downloadFromRemote = async (
|
||||||
client: WebDAVClient,
|
client: WrappedWebdavClient,
|
||||||
fileOrFolderPath: string,
|
fileOrFolderPath: string,
|
||||||
vault: Vault,
|
vault: Vault,
|
||||||
mtime: number,
|
mtime: number,
|
||||||
password: string = "",
|
password: string = "",
|
||||||
remoteEncryptedKey: string = ""
|
remoteEncryptedKey: string = ""
|
||||||
) => {
|
) => {
|
||||||
|
await client.init();
|
||||||
|
|
||||||
const isFolder = fileOrFolderPath.endsWith("/");
|
const isFolder = fileOrFolderPath.endsWith("/");
|
||||||
|
|
||||||
await mkdirpInVault(fileOrFolderPath, vault);
|
await mkdirpInVault(fileOrFolderPath, vault);
|
||||||
@ -189,7 +259,7 @@ export const downloadFromRemote = async (
|
|||||||
if (password !== "") {
|
if (password !== "") {
|
||||||
downloadFile = remoteEncryptedKey;
|
downloadFile = remoteEncryptedKey;
|
||||||
}
|
}
|
||||||
downloadFile = getWebdavPath(downloadFile);
|
downloadFile = getWebdavPath(downloadFile, client.vaultName);
|
||||||
const remoteContent = await downloadFromRemoteRaw(client, downloadFile);
|
const remoteContent = await downloadFromRemoteRaw(client, downloadFile);
|
||||||
let localContent = remoteContent;
|
let localContent = remoteContent;
|
||||||
if (password !== "") {
|
if (password !== "") {
|
||||||
@ -202,7 +272,7 @@ export const downloadFromRemote = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const deleteFromRemote = async (
|
export const deleteFromRemote = async (
|
||||||
client: WebDAVClient,
|
client: WrappedWebdavClient,
|
||||||
fileOrFolderPath: string,
|
fileOrFolderPath: string,
|
||||||
password: string = "",
|
password: string = "",
|
||||||
remoteEncryptedKey: string = ""
|
remoteEncryptedKey: string = ""
|
||||||
@ -214,9 +284,11 @@ export const deleteFromRemote = async (
|
|||||||
if (password !== "") {
|
if (password !== "") {
|
||||||
remoteFileName = remoteEncryptedKey;
|
remoteFileName = remoteEncryptedKey;
|
||||||
}
|
}
|
||||||
remoteFileName = getWebdavPath(remoteFileName);
|
remoteFileName = getWebdavPath(remoteFileName, client.vaultName);
|
||||||
|
|
||||||
|
await client.init();
|
||||||
try {
|
try {
|
||||||
await client.deleteFile(remoteFileName);
|
await client.client.deleteFile(remoteFileName);
|
||||||
// console.log(`delete ${remoteFileName} succeeded`);
|
// console.log(`delete ${remoteFileName} succeeded`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("some error while deleting");
|
console.error("some error while deleting");
|
||||||
@ -224,7 +296,8 @@ export const deleteFromRemote = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const checkConnectivity = async (client: WebDAVClient) => {
|
export const checkConnectivity = async (client: WrappedWebdavClient) => {
|
||||||
|
await client.init();
|
||||||
try {
|
try {
|
||||||
const results = await getRemoteMeta(client, "/");
|
const results = await getRemoteMeta(client, "/");
|
||||||
if (results === undefined) {
|
if (results === undefined) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user