fix all fsXxxx.ts

This commit is contained in:
fyears 2024-04-21 22:39:51 +08:00
parent 1e7298dc3e
commit 6f0f0d984a
4 changed files with 66 additions and 67 deletions

View File

@ -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.`

View File

@ -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();

View File

@ -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.`

View File

@ -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) => {