fix all fsXxxx.ts
This commit is contained in:
parent
1e7298dc3e
commit
6f0f0d984a
|
@ -1,10 +1,11 @@
|
|||
import { FakeFs, FakeStats } from "./fsAll";
|
||||
import { FakeFs } from "./fsAll";
|
||||
import { Dropbox, DropboxAuth } from "dropbox";
|
||||
import type { files, DropboxResponseError, DropboxResponse } from "dropbox";
|
||||
import {
|
||||
DropboxConfig,
|
||||
COMMAND_CALLBACK_DROPBOX,
|
||||
OAUTH2_FORCE_EXPIRE_MILLISECONDS,
|
||||
Entity,
|
||||
} from "./baseTypes";
|
||||
import random from "lodash/random";
|
||||
import {
|
||||
|
@ -62,13 +63,13 @@ const getNormPath = (fileOrFolderPath: string, remoteBaseDir: string) => {
|
|||
return fileOrFolderPath.slice(`/${remoteBaseDir}/`.length);
|
||||
};
|
||||
|
||||
const fromDropboxItemToFakeStats = (
|
||||
const fromDropboxItemToEntity = (
|
||||
x:
|
||||
| files.FileMetadataReference
|
||||
| files.FolderMetadataReference
|
||||
| files.DeletedMetadataReference,
|
||||
remoteBaseDir: string
|
||||
): FakeStats => {
|
||||
): Entity => {
|
||||
let key = getNormPath(x.path_display!, remoteBaseDir);
|
||||
if (x[".tag"] === "folder" && !key.endsWith("/")) {
|
||||
key = `${key}/`;
|
||||
|
@ -76,19 +77,23 @@ const fromDropboxItemToFakeStats = (
|
|||
|
||||
if (x[".tag"] === "folder") {
|
||||
return {
|
||||
key: key,
|
||||
keyRaw: key,
|
||||
size: 0,
|
||||
sizeRaw: 0,
|
||||
} as FakeStats;
|
||||
} as Entity;
|
||||
} else if (x[".tag"] === "file") {
|
||||
const mtimeCli = Date.parse(x.client_modified).valueOf();
|
||||
const mtimeSvr = Date.parse(x.server_modified).valueOf();
|
||||
return {
|
||||
key: key,
|
||||
keyRaw: key,
|
||||
mtimeCli: mtimeCli,
|
||||
mtimeSvr: mtimeSvr,
|
||||
size: x.size,
|
||||
sizeRaw: x.size,
|
||||
hash: x.content_hash,
|
||||
} as FakeStats;
|
||||
} as Entity;
|
||||
} else {
|
||||
// x[".tag"] === "deleted"
|
||||
throw Error("do not support deleted tag");
|
||||
|
@ -100,7 +105,7 @@ const fromDropboxItemToFakeStats = (
|
|||
* https://www.dropboxforum.com/t5/Dropbox-API-Support-Feedback/Case-Sensitivity-in-API-2/td-p/191279
|
||||
* @param entities
|
||||
*/
|
||||
export const fixFakeStatsListCasesInplace = (entities: { key?: string }[]) => {
|
||||
export const fixEntityListCasesInplace = (entities: { key?: string }[]) => {
|
||||
for (const iterator of entities) {
|
||||
if (iterator.key === undefined) {
|
||||
throw Error(`dropbox list should all have key, but meet undefined`);
|
||||
|
@ -446,7 +451,7 @@ export class FakeFsDropbox extends FakeFs {
|
|||
return this;
|
||||
}
|
||||
|
||||
async walk(): Promise<FakeStats[]> {
|
||||
async walk(): Promise<Entity[]> {
|
||||
await this._init();
|
||||
|
||||
let res = await this.dropbox.filesListFolder({
|
||||
|
@ -464,7 +469,7 @@ export class FakeFsDropbox extends FakeFs {
|
|||
const unifiedContents = contents
|
||||
.filter((x) => x[".tag"] !== "deleted")
|
||||
.filter((x) => x.path_display !== `/${this.remoteBaseDir}`)
|
||||
.map((x) => fromDropboxItemToFakeStats(x, this.remoteBaseDir));
|
||||
.map((x) => fromDropboxItemToEntity(x, this.remoteBaseDir));
|
||||
|
||||
while (res.result.has_more) {
|
||||
res = await this.dropbox.filesListFolderContinue({
|
||||
|
@ -478,21 +483,21 @@ export class FakeFsDropbox extends FakeFs {
|
|||
const unifiedContents2 = contents2
|
||||
.filter((x) => x[".tag"] !== "deleted")
|
||||
.filter((x) => x.path_display !== `/${this.remoteBaseDir}`)
|
||||
.map((x) => fromDropboxItemToFakeStats(x, this.remoteBaseDir));
|
||||
.map((x) => fromDropboxItemToEntity(x, this.remoteBaseDir));
|
||||
unifiedContents.push(...unifiedContents2);
|
||||
}
|
||||
|
||||
fixFakeStatsListCasesInplace(unifiedContents);
|
||||
fixEntityListCasesInplace(unifiedContents);
|
||||
|
||||
return unifiedContents;
|
||||
}
|
||||
|
||||
async stat(key: string): Promise<FakeStats> {
|
||||
async stat(key: string): Promise<Entity> {
|
||||
await this._init();
|
||||
return await this._statFromRoot(getDropboxPath(key, this.remoteBaseDir));
|
||||
}
|
||||
|
||||
async mkdir(key: string, mtime: number, ctime: number): Promise<FakeStats> {
|
||||
async mkdir(key: string, mtime: number, ctime: number): Promise<Entity> {
|
||||
if (!key.endsWith("/")) {
|
||||
throw Error(`you should not call mkdir on ${key}`);
|
||||
}
|
||||
|
@ -508,7 +513,7 @@ export class FakeFsDropbox extends FakeFs {
|
|||
content: ArrayBuffer,
|
||||
mtime: number,
|
||||
ctime: number
|
||||
): Promise<FakeStats> {
|
||||
): Promise<Entity> {
|
||||
if (key.endsWith("/")) {
|
||||
throw Error(`you should not call writeFile on ${key}`);
|
||||
}
|
||||
|
@ -586,7 +591,7 @@ export class FakeFsDropbox extends FakeFs {
|
|||
}
|
||||
}
|
||||
|
||||
async _statFromRoot(key: string): Promise<FakeStats> {
|
||||
async _statFromRoot(key: string): Promise<Entity> {
|
||||
// if (key === "" || key === "/") {
|
||||
// // filesGetMetadata doesn't support root folder
|
||||
// // we instead try to list files
|
||||
|
@ -620,14 +625,14 @@ export class FakeFsDropbox extends FakeFs {
|
|||
if (rsp.status !== 200) {
|
||||
throw Error(JSON.stringify(rsp));
|
||||
}
|
||||
return fromDropboxItemToFakeStats(rsp.result, this.remoteBaseDir);
|
||||
return fromDropboxItemToEntity(rsp.result, this.remoteBaseDir);
|
||||
}
|
||||
|
||||
async _mkdirFromRoot(
|
||||
key: string,
|
||||
mtime: number,
|
||||
ctime: number
|
||||
): Promise<FakeStats> {
|
||||
): Promise<Entity> {
|
||||
if (hasEmojiInText(key)) {
|
||||
throw new Error(
|
||||
`${key}: Error: Dropbox does not support emoji in file / folder names.`
|
||||
|
@ -667,7 +672,7 @@ export class FakeFsDropbox extends FakeFs {
|
|||
mtime: number,
|
||||
ctime: number,
|
||||
origKey: string
|
||||
): Promise<FakeStats> {
|
||||
): Promise<Entity> {
|
||||
if (hasEmojiInText(origKey)) {
|
||||
throw new Error(
|
||||
`${origKey}: Error: Dropbox does not support emoji in file / folder names.`
|
||||
|
|
|
@ -51,17 +51,15 @@ function isLikelyEncryptedNameNotMatchMethod(
|
|||
export interface PasswordCheckType {
|
||||
ok: boolean;
|
||||
reason:
|
||||
| "empty_remote"
|
||||
| "unknown_encryption_method"
|
||||
| "remote_encrypted_local_no_password"
|
||||
| "password_matched"
|
||||
| "password_or_method_not_matched_or_remote_not_encrypted"
|
||||
| "likely_no_password_both_sides"
|
||||
| "encryption_method_not_matched";
|
||||
| "empty_remote"
|
||||
| "unknown_encryption_method"
|
||||
| "remote_encrypted_local_no_password"
|
||||
| "password_matched"
|
||||
| "password_or_method_not_matched_or_remote_not_encrypted"
|
||||
| "likely_no_password_both_sides"
|
||||
| "encryption_method_not_matched";
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class FakeFsEncrypt extends FakeFs {
|
||||
innerFs: FakeFs;
|
||||
readonly password: string;
|
||||
|
@ -108,8 +106,9 @@ export class FakeFsEncrypt extends FakeFs {
|
|||
async _getInnerWalkResult(): Promise<Entity[]> {
|
||||
let innerWalkResult: Entity[] | undefined = undefined;
|
||||
if (
|
||||
this.innerWalkResultCacheTime !== undefined &&
|
||||
this.innerWalkResultCacheTime >= Date.now() - 1000) {
|
||||
this.innerWalkResultCacheTime !== undefined &&
|
||||
this.innerWalkResultCacheTime >= Date.now() - 1000
|
||||
) {
|
||||
innerWalkResult = this.innerWalkResultCache!;
|
||||
} else {
|
||||
innerWalkResult = await this.innerFs.walk();
|
||||
|
@ -121,7 +120,7 @@ export class FakeFsEncrypt extends FakeFs {
|
|||
|
||||
async isPasswordOk(): Promise<PasswordCheckType> {
|
||||
const innerWalkResult = await this._getInnerWalkResult();
|
||||
|
||||
|
||||
if (innerWalkResult === undefined || innerWalkResult.length === 0) {
|
||||
// remote empty
|
||||
return {
|
||||
|
@ -152,9 +151,7 @@ export class FakeFsEncrypt extends FakeFs {
|
|||
reason: "unknown_encryption_method",
|
||||
};
|
||||
}
|
||||
if (
|
||||
isLikelyEncryptedNameNotMatchMethod(santyCheckKey, this.method)
|
||||
) {
|
||||
if (isLikelyEncryptedNameNotMatchMethod(santyCheckKey, this.method)) {
|
||||
return {
|
||||
ok: false,
|
||||
reason: "encryption_method_not_matched",
|
||||
|
@ -176,7 +173,7 @@ export class FakeFsEncrypt extends FakeFs {
|
|||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async walk(): Promise<Entity[]> {
|
||||
const innerWalkResult = await this._getInnerWalkResult();
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import {
|
||||
COMMAND_CALLBACK_ONEDRIVE,
|
||||
DEFAULT_CONTENT_TYPE,
|
||||
Entity,
|
||||
OAUTH2_FORCE_EXPIRE_MILLISECONDS,
|
||||
OnedriveConfig,
|
||||
VALID_REQURL,
|
||||
} from "./baseTypes";
|
||||
import { FakeFs, FakeStats } from "./fsAll";
|
||||
import { FakeFs } from "./fsAll";
|
||||
import { bufferToArrayBuffer } from "./misc";
|
||||
import { request, requestUrl } from "obsidian";
|
||||
import { CryptoProvider } from "@azure/msal-node/dist/crypto/CryptoProvider";
|
||||
|
@ -231,16 +232,13 @@ const getOnedrivePath = (fileOrFolderPath: string, remoteBaseDir: string) => {
|
|||
return key;
|
||||
};
|
||||
|
||||
const constructFromDriveItemToFakeStatsError = (x: DriveItem) => {
|
||||
const constructFromDriveItemToEntityError = (x: DriveItem) => {
|
||||
return `parentPath="${
|
||||
x.parentReference?.path ?? "(no parentReference or path)"
|
||||
}", selfName="${x.name}"`;
|
||||
};
|
||||
|
||||
const fromDriveItemToFakeStats = (
|
||||
x: DriveItem,
|
||||
remoteBaseDir: string
|
||||
): FakeStats => {
|
||||
const fromDriveItemToEntity = (x: DriveItem, remoteBaseDir: string): Entity => {
|
||||
let key = "";
|
||||
|
||||
// possible prefix:
|
||||
|
@ -320,14 +318,14 @@ const fromDriveItemToFakeStats = (
|
|||
key = x.name;
|
||||
} else {
|
||||
throw Error(
|
||||
`we meet file/folder and do not know how to deal with it:\n${constructFromDriveItemToFakeStatsError(
|
||||
`we meet file/folder and do not know how to deal with it:\n${constructFromDriveItemToEntityError(
|
||||
x
|
||||
)}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw Error(
|
||||
`we meet file/folder and do not know how to deal with it:\n${constructFromDriveItemToFakeStatsError(
|
||||
`we meet file/folder and do not know how to deal with it:\n${constructFromDriveItemToEntityError(
|
||||
x
|
||||
)}`
|
||||
);
|
||||
|
@ -342,9 +340,11 @@ const fromDriveItemToFakeStats = (
|
|||
const mtimeCli = Date.parse(x?.fileSystemInfo!.lastModifiedDateTime!);
|
||||
return {
|
||||
key: key,
|
||||
keyRaw: key,
|
||||
mtimeSvr: mtimeSvr,
|
||||
mtimeCli: mtimeCli,
|
||||
size: isFolder ? 0 : x.size!,
|
||||
sizeRaw: isFolder ? 0 : x.size!,
|
||||
// hash: ?? // TODO
|
||||
};
|
||||
};
|
||||
|
@ -637,7 +637,7 @@ export class FakeFsOnedrive extends FakeFs {
|
|||
* Use delta api to list all files and folders
|
||||
* https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_delta?view=odsp-graph-online
|
||||
*/
|
||||
async walk(): Promise<FakeStats[]> {
|
||||
async walk(): Promise<Entity[]> {
|
||||
await this._init();
|
||||
|
||||
const NEXT_LINK_KEY = "@odata.nextLink";
|
||||
|
@ -662,30 +662,30 @@ export class FakeFsOnedrive extends FakeFs {
|
|||
|
||||
// unify everything to Entity
|
||||
const unifiedContents = driveItems
|
||||
.map((x) => fromDriveItemToFakeStats(x, this.remoteBaseDir))
|
||||
.map((x) => fromDriveItemToEntity(x, this.remoteBaseDir))
|
||||
.filter((x) => x.key !== "/");
|
||||
|
||||
return unifiedContents;
|
||||
}
|
||||
|
||||
async stat(key: string): Promise<FakeStats> {
|
||||
async stat(key: string): Promise<Entity> {
|
||||
await this._init();
|
||||
return await this._statFromRoot(getOnedrivePath(key, this.remoteBaseDir));
|
||||
}
|
||||
|
||||
async _statFromRoot(key: string): Promise<FakeStats> {
|
||||
async _statFromRoot(key: string): Promise<Entity> {
|
||||
// console.info(`remotePath=${remotePath}`);
|
||||
const rsp = await this._getJson(
|
||||
`${key}?$select=cTag,eTag,fileSystemInfo,folder,file,name,parentReference,size`
|
||||
);
|
||||
// console.info(rsp);
|
||||
const driveItem = rsp as DriveItem;
|
||||
const res = fromDriveItemToFakeStats(driveItem, this.remoteBaseDir);
|
||||
const res = fromDriveItemToEntity(driveItem, this.remoteBaseDir);
|
||||
// console.info(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
async mkdir(key: string, mtime: number, ctime: number): Promise<FakeStats> {
|
||||
async mkdir(key: string, mtime: number, ctime: number): Promise<Entity> {
|
||||
if (!key.endsWith("/")) {
|
||||
throw Error(`you should not call mkdir on ${key}`);
|
||||
}
|
||||
|
@ -699,7 +699,7 @@ export class FakeFsOnedrive extends FakeFs {
|
|||
key: string,
|
||||
mtime: number,
|
||||
ctime: number
|
||||
): Promise<FakeStats> {
|
||||
): Promise<Entity> {
|
||||
if (this.foldersCreatedBefore.has(key)) {
|
||||
// created, pass
|
||||
} else {
|
||||
|
@ -732,7 +732,7 @@ export class FakeFsOnedrive extends FakeFs {
|
|||
content: ArrayBuffer,
|
||||
mtime: number,
|
||||
ctime: number
|
||||
): Promise<FakeStats> {
|
||||
): Promise<Entity> {
|
||||
if (key.endsWith("/")) {
|
||||
throw Error(`you should not call writeFile on ${key}`);
|
||||
}
|
||||
|
@ -754,7 +754,7 @@ export class FakeFsOnedrive extends FakeFs {
|
|||
mtime: number,
|
||||
ctime: number,
|
||||
origKey: string
|
||||
): Promise<FakeStats> {
|
||||
): Promise<Entity> {
|
||||
if (content.byteLength === 0) {
|
||||
throw Error(
|
||||
`${origKey}: Empty file is not allowed in OneDrive, and please write something in it.`
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Platform, requestUrl } from "obsidian";
|
||||
import { getReasonPhrase } from "http-status-codes/build/cjs/utils-functions";
|
||||
import { FakeFs, FakeStats } from "./fsAll";
|
||||
import { VALID_REQURL, WebdavConfig } from "./baseTypes";
|
||||
import { FakeFs } from "./fsAll";
|
||||
import { Entity, VALID_REQURL, WebdavConfig } from "./baseTypes";
|
||||
import type {
|
||||
FileStat,
|
||||
WebDAVClient,
|
||||
|
@ -184,10 +184,7 @@ const getNormPath = (fileOrFolderPath: string, remoteBaseDir: string) => {
|
|||
return fileOrFolderPath.slice(`/${remoteBaseDir}/`.length);
|
||||
};
|
||||
|
||||
const fromWebdavItemToFakeStats = (
|
||||
x: FileStat,
|
||||
remoteBaseDir: string
|
||||
): FakeStats => {
|
||||
const fromWebdavItemToEntity = (x: FileStat, remoteBaseDir: string): Entity => {
|
||||
let key = getNormPath(x.filename, remoteBaseDir);
|
||||
if (x.type === "directory" && !key.endsWith("/")) {
|
||||
key = `${key}/`;
|
||||
|
@ -195,9 +192,11 @@ const fromWebdavItemToFakeStats = (
|
|||
const mtimeSvr = Date.parse(x.lastmod).valueOf();
|
||||
return {
|
||||
key: key,
|
||||
keyRaw: key,
|
||||
mtimeSvr: mtimeSvr,
|
||||
mtimeCli: mtimeSvr, // TODO: no universal way to set mtime in webdav
|
||||
size: x.size,
|
||||
sizeRaw: x.size,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -293,7 +292,7 @@ export class FakeFsWebdav extends FakeFs {
|
|||
}
|
||||
}
|
||||
|
||||
async walk(): Promise<FakeStats[]> {
|
||||
async walk(): Promise<Entity[]> {
|
||||
await this._init();
|
||||
|
||||
let contents = [] as FileStat[];
|
||||
|
@ -352,25 +351,23 @@ export class FakeFsWebdav extends FakeFs {
|
|||
}
|
||||
)) as FileStat[];
|
||||
}
|
||||
return contents.map((x) =>
|
||||
fromWebdavItemToFakeStats(x, this.remoteBaseDir)
|
||||
);
|
||||
return contents.map((x) => fromWebdavItemToEntity(x, this.remoteBaseDir));
|
||||
}
|
||||
|
||||
async stat(key: string): Promise<FakeStats> {
|
||||
async stat(key: string): Promise<Entity> {
|
||||
await this._init();
|
||||
const fullPath = getWebdavPath(key, this.remoteBaseDir);
|
||||
return await this._statFromRoot(fullPath);
|
||||
}
|
||||
|
||||
async _statFromRoot(key: string): Promise<FakeStats> {
|
||||
async _statFromRoot(key: string): Promise<Entity> {
|
||||
const res = (await this.client.stat(key, {
|
||||
details: false,
|
||||
})) as FileStat;
|
||||
return fromWebdavItemToFakeStats(res, this.remoteBaseDir);
|
||||
return fromWebdavItemToEntity(res, this.remoteBaseDir);
|
||||
}
|
||||
|
||||
async mkdir(key: string, mtime: number, ctime: number): Promise<FakeStats> {
|
||||
async mkdir(key: string, mtime: number, ctime: number): Promise<Entity> {
|
||||
if (!key.endsWith("/")) {
|
||||
throw Error(`you should not call mkdir on ${key}`);
|
||||
}
|
||||
|
@ -383,7 +380,7 @@ export class FakeFsWebdav extends FakeFs {
|
|||
key: string,
|
||||
mtime: number,
|
||||
ctime: number
|
||||
): Promise<FakeStats> {
|
||||
): Promise<Entity> {
|
||||
await this.client.createDirectory(key, {
|
||||
recursive: true,
|
||||
});
|
||||
|
@ -395,7 +392,7 @@ export class FakeFsWebdav extends FakeFs {
|
|||
content: ArrayBuffer,
|
||||
mtime: number,
|
||||
ctime: number
|
||||
): Promise<FakeStats> {
|
||||
): Promise<Entity> {
|
||||
if (key.endsWith("/")) {
|
||||
throw Error(`you should not call writeFile on ${key}`);
|
||||
}
|
||||
|
@ -409,7 +406,7 @@ export class FakeFsWebdav extends FakeFs {
|
|||
content: ArrayBuffer,
|
||||
mtime: number,
|
||||
ctime: number
|
||||
): Promise<FakeStats> {
|
||||
): Promise<Entity> {
|
||||
await this.client.putFileContents(key, content, {
|
||||
overwrite: true,
|
||||
onUploadProgress: (progress: any) => {
|
||||
|
|
Loading…
Reference in New Issue