diff --git a/README.md b/README.md index 0ae3b27..ca50f9a 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ This is yet another unofficial sync plugin for Obsidian. If you like it or find ## Limitations -- **To support deltions sync, extra metadata will also be uploaded.** See [Minimal Intrusive](./docs/minimal_intrusive_design.md). +- **To support deletions sync, extra metadata will also be uploaded.** See [Minimal Intrusive](./docs/minimal_intrusive_design.md). - **No Conflict resolution. No content-diff-and-patch algorithm.** All files and folders are compared using their local and remote "last modified time" and those with later "last modified time" wins. - **Cloud services cost you money.** Always be aware of the costs and pricing. Specifically, all the operations, including but not limited to downloading, uploading, listing all files, calling any api, storage sizes, may or may not cost you money. - **Some limitations from the browser environment.** More technical details are [in the doc](./docs/browser_env.md). diff --git a/docs/services_connectable_or_not.md b/docs/services_connectable_or_not.md index af6d2fd..61febef 100644 --- a/docs/services_connectable_or_not.md +++ b/docs/services_connectable_or_not.md @@ -26,7 +26,7 @@ The list is for information purposes only. | [TeraCLOUD](https://teracloud.jp/en/) | Yes | | Yes | | Yes | No CORS support. | | Dropbox | Yes | | | Yes | | | | OneDrive for personal | Yes | | | Yes | | | -| OneDrive for Business | In the plan | | | ? | | | +| OneDrive for Business | Yes | | | ? | | | | Google Drive | In the plan | | | ? | | | | [Box](https://www.box.com/) | ? | | | May be possible but needs further development. | | | | Google Cloud Storage | ? | | | May be possible but needs further development. | | | diff --git a/esbuild.config.mjs b/esbuild.config.mjs index 7eb193a..7e3753d 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -18,7 +18,7 @@ const DEFAULT_ONEDRIVE_CLIENT_ID = process.env.ONEDRIVE_CLIENT_ID || ""; const DEFAULT_ONEDRIVE_AUTHORITY = process.env.ONEDRIVE_AUTHORITY || ""; esbuild - .build({ + .context({ banner: { js: banner, }, @@ -33,11 +33,13 @@ esbuild "fs", "tls", "net", + "http", + "https", // ...builtins ], inject: ["./esbuild.injecthelper.mjs"], format: "cjs", - watch: !prod, + // watch: !prod, // no longer valid in esbuild 0.17 target: "es2016", logLevel: "info", sourcemap: prod ? false : "inline", @@ -53,4 +55,15 @@ esbuild "process.env.DEBUG": `undefined`, // ugly fix }, }) + .then((context) => { + if (process.argv.includes("--watch")) { + // Enable watch mode + context.watch(); + } else { + // Build once and exit if not in watch mode + context.rebuild().then((result) => { + context.dispose(); + }); + } + }) .catch(() => process.exit(1)); diff --git a/package.json b/package.json index d0281eb..2e99cd6 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,11 @@ "version": "0.3.25", "description": "This is yet another sync plugin for Obsidian app.", "scripts": { - "dev2": "node esbuild.config.mjs", + "dev2": "node esbuild.config.mjs --watch", "build2": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", "build": "webpack --mode production", "dev": "webpack --mode development --watch", - "format": "npx prettier --write .", + "format": "npx prettier --trailing-comma es5 --write .", "clean": "npx rimraf main.js", "test": "cross-env TS_NODE_COMPILER_OPTIONS={\\\"module\\\":\\\"commonjs\\\"} mocha -r ts-node/register 'tests/**/*.ts'" }, @@ -23,73 +23,74 @@ "author": "", "license": "Apache-2.0", "devDependencies": { - "@microsoft/microsoft-graph-types": "^2.19.0", - "@types/chai": "^4.3.1", - "@types/chai-as-promised": "^7.1.5", - "@types/jsdom": "^16.2.14", - "@types/lodash": "^4.14.182", - "@types/mime-types": "^2.1.1", - "@types/mocha": "^9.1.1", - "@types/mustache": "^4.1.2", - "@types/node": "^17.0.30", - "@types/qrcode": "^1.4.2", - "builtin-modules": "^3.2.0", - "chai": "^4.3.6", + "@microsoft/microsoft-graph-types": "^2.40.0", + "@types/chai": "^4.3.11", + "@types/chai-as-promised": "^7.1.8", + "@types/jsdom": "^21.1.6", + "@types/lodash": "^4.14.202", + "@types/mime-types": "^2.1.4", + "@types/mocha": "^10.0.6", + "@types/mustache": "^4.2.5", + "@types/node": "^20.10.4", + "@types/qrcode": "^1.5.5", + "builtin-modules": "^3.3.0", + "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "cross-env": "^7.0.3", - "dotenv": "^16.0.0", - "esbuild": "^0.14.38", - "jsdom": "^19.0.0", - "mocha": "^9.2.2", - "prettier": "^2.6.2", - "ts-loader": "^9.2.9", - "ts-node": "^10.7.0", - "tslib": "^2.4.0", - "typescript": "^4.6.4", + "dotenv": "^16.3.1", + "esbuild": "^0.19.9", + "jsdom": "^23.0.1", + "mocha": "^10.2.0", + "npm-check-updates": "^16.14.12", + "obsidian": "^1.4.11", + "prettier": "^3.1.1", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "tslib": "^2.6.2", + "typescript": "^5.3.3", "webdav-server": "^2.6.2", - "webpack": "^5.72.0", - "webpack-cli": "^4.9.2" + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4" }, "dependencies": { - "@aws-sdk/client-s3": "^3.81.0", - "@aws-sdk/fetch-http-handler": "^3.78.0", - "@aws-sdk/lib-storage": "^3.81.0", - "@aws-sdk/protocol-http": "^3.78.0", - "@aws-sdk/querystring-builder": "^3.78.0", - "@aws-sdk/signature-v4-crt": "^3.78.0", - "@aws-sdk/types": "^3.78.0", - "@azure/msal-node": "^1.8.0", + "@aws-sdk/client-s3": "^3.474.0", + "@aws-sdk/lib-storage": "^3.474.0", + "@aws-sdk/signature-v4-crt": "^3.474.0", + "@aws-sdk/types": "^3.468.0", + "@azure/msal-node": "^2.6.0", "@fyears/tsqueue": "^1.0.1", - "@microsoft/microsoft-graph-client": "^3.0.2", - "acorn": "^8.7.1", - "aggregate-error": "^4.0.0", - "assert": "^2.0.0", - "aws-crt": "^1.12.1", + "@microsoft/microsoft-graph-client": "^3.0.7", + "@smithy/fetch-http-handler": "^2.3.1", + "@smithy/protocol-http": "^3.0.11", + "@smithy/querystring-builder": "^2.0.15", + "acorn": "^8.11.2", + "aggregate-error": "^5.0.0", + "assert": "^2.1.0", + "aws-crt": "^1.20.0", "buffer": "^6.0.3", "crypto-browserify": "^3.12.0", - "delay": "^5.0.0", - "dropbox": "^10.28.0", - "emoji-regex": "^10.1.0", - "http-status-codes": "^2.2.0", + "delay": "^6.0.0", + "dropbox": "^10.34.0", + "emoji-regex": "^10.3.0", + "http-status-codes": "^2.3.0", "localforage": "^1.10.0", "lodash": "^4.17.21", - "loglevel": "^1.8.0", - "lucide": "^0.35.0", + "loglevel": "^1.8.1", + "lucide": "^0.298.0", "mime-types": "^2.1.35", "mustache": "^4.2.0", - "nanoid": "^3.3.3", - "obsidian": "^0.14.6", - "p-queue": "^7.2.0", + "nanoid": "^5.0.4", + "p-queue": "^8.0.1", "path-browserify": "^1.0.1", "process": "^0.11.10", - "qrcode": "^1.5.0", - "rfc4648": "^1.5.1", - "rimraf": "^3.0.2", + "qrcode": "^1.5.3", + "rfc4648": "^1.5.3", + "rimraf": "^5.0.5", "stream-browserify": "^3.0.0", - "url": "^0.11.0", - "util": "^0.12.4", - "webdav": "^4.9.0", + "url": "^0.11.3", + "util": "^0.12.5", + "webdav": "^5.3.1", "webdav-fs": "^4.0.1", - "xregexp": "^5.1.0" + "xregexp": "^5.1.1" } } diff --git a/src/i18n.ts b/src/i18n.ts index 39af339..349e81b 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -5,7 +5,7 @@ import { LANGS } from "./langs"; export type LangType = keyof typeof LANGS; export type LangTypeAndAuto = LangType | "auto"; -export type TransItemType = keyof typeof LANGS["en"]; +export type TransItemType = keyof (typeof LANGS)["en"]; export class I18n { lang: LangTypeAndAuto; @@ -31,7 +31,7 @@ export class I18n { } const res: string = - (LANGS[realLang] as typeof LANGS["en"])[key] || LANGS["en"][key] || key; + (LANGS[realLang] as (typeof LANGS)["en"])[key] || LANGS["en"][key] || key; return res; } diff --git a/src/localdb.ts b/src/localdb.ts index 01b7b51..e214fca 100644 --- a/src/localdb.ts +++ b/src/localdb.ts @@ -312,9 +312,8 @@ export const clearDeleteRenameHistoryOfKeyAndVault = async ( vaultRandomID: string ) => { const fullKey = `${vaultRandomID}\t${key}`; - const item: FileFolderHistoryRecord | null = await db.fileHistoryTbl.getItem( - fullKey - ); + const item: FileFolderHistoryRecord | null = + await db.fileHistoryTbl.getItem(fullKey); if ( item !== null && (item.actionType === "delete" || item.actionType === "rename") diff --git a/src/main.ts b/src/main.ts index 1656afe..bc9de28 100644 --- a/src/main.ts +++ b/src/main.ts @@ -976,9 +976,8 @@ export default class RemotelySavePlugin extends Plugin { const pluginConfigDir = this.manifest.dir || `${this.app.vault.configDir}/plugins/${this.manifest.dir}`; - const pluginConfigDirExists = await this.app.vault.adapter.exists( - pluginConfigDir - ); + const pluginConfigDirExists = + await this.app.vault.adapter.exists(pluginConfigDir); if (!pluginConfigDirExists) { // what happened? return; diff --git a/src/moreOnLog.ts b/src/moreOnLog.ts index 4648dbc..11d146a 100644 --- a/src/moreOnLog.ts +++ b/src/moreOnLog.ts @@ -4,14 +4,20 @@ import { TAbstractFile, TFolder, TFile, Vault } from "obsidian"; import * as origLog from "loglevel"; -import type { LogLevelNumbers, Logger, LogLevel, LogLevelDesc } from "loglevel"; +import type { + LogLevelNumbers, + Logger, + LogLevel, + LogLevelDesc, + LogLevelNames, +} from "loglevel"; const log2 = origLog.getLogger("rs-default"); const originalFactory = log2.methodFactory; export const applyLogWriterInplace = function (writer: (...msg: any[]) => any) { log2.methodFactory = function ( - methodName: string, + methodName: LogLevelNames, logLevel: LogLevelNumbers, loggerName: string | symbol ) { diff --git a/src/remoteForDropbox.ts b/src/remoteForDropbox.ts index ccf16ad..8c0de69 100644 --- a/src/remoteForDropbox.ts +++ b/src/remoteForDropbox.ts @@ -1,4 +1,4 @@ -import delay from "delay"; +import { rangeDelay } from "delay"; import { Dropbox, DropboxAuth } from "dropbox"; import type { files, DropboxResponseError, DropboxResponse } from "dropbox"; import { Vault } from "obsidian"; @@ -340,7 +340,7 @@ async function retryReq( 2 )}` ); - await delay.range(secMin * 1000, secMax * 1000); + await rangeDelay(secMin * 1000, secMax * 1000); } } } diff --git a/src/remoteForS3.ts b/src/remoteForS3.ts index afeb47a..e028888 100644 --- a/src/remoteForS3.ts +++ b/src/remoteForS3.ts @@ -11,14 +11,14 @@ import { S3Client, } from "@aws-sdk/client-s3"; import { Upload } from "@aws-sdk/lib-storage"; -import { HttpHandler, HttpRequest, HttpResponse } from "@aws-sdk/protocol-http"; +import { HttpHandler, HttpRequest, HttpResponse } from "@smithy/protocol-http"; import { FetchHttpHandler, FetchHttpHandlerOptions, -} from "@aws-sdk/fetch-http-handler"; +} from "@smithy/fetch-http-handler"; // @ts-ignore -import { requestTimeout } from "@aws-sdk/fetch-http-handler/dist-es/request-timeout"; -import { buildQueryString } from "@aws-sdk/querystring-builder"; +import { requestTimeout } from "@smithy/fetch-http-handler/dist-es/request-timeout"; +import { buildQueryString } from "@smithy/querystring-builder"; import { HeaderBag, HttpHandlerOptions, Provider } from "@aws-sdk/types"; import { Buffer } from "buffer"; import * as mime from "mime-types"; diff --git a/src/remoteForWebdav.ts b/src/remoteForWebdav.ts index 3532874..d305e11 100644 --- a/src/remoteForWebdav.ts +++ b/src/remoteForWebdav.ts @@ -17,8 +17,8 @@ import type { RequestOptionsWithState, Response, ResponseDataDetailed, -} from "webdav/web"; -import { getPatcher } from "webdav/web"; +} from "webdav"; +import { getPatcher } from "webdav"; if (VALID_REQURL) { getPatcher().patch( "request", @@ -38,28 +38,28 @@ if (VALID_REQURL) { }); let r2: Response | ResponseDataDetailed = undefined; - if (options.responseType === undefined) { + if ((options as any).responseType === undefined) { r2 = { data: undefined, status: r.status, statusText: getReasonPhrase(r.status), headers: r.headers, }; - } else if (options.responseType === "json") { + } else if ((options as any).responseType === "json") { r2 = { data: r.json, status: r.status, statusText: getReasonPhrase(r.status), headers: r.headers, }; - } else if (options.responseType === "text") { + } else if ((options as any).responseType === "text") { r2 = { data: r.text, status: r.status, statusText: getReasonPhrase(r.status), headers: r.headers, }; - } else if (options.responseType === "arraybuffer") { + } else if ((options as any).responseType === "arraybuffer") { r2 = { data: r.arrayBuffer, status: r.status, @@ -68,7 +68,9 @@ if (VALID_REQURL) { }; } else { throw Error( - `do not know how to deal with responseType = ${options.responseType}` + `do not know how to deal with responseType = ${ + (options as any).responseType + }` ); } return r2; @@ -108,8 +110,8 @@ if (VALID_REQURL) { // // console.log("using fetch"); // return r; // }); -import { AuthType, BufferLike, createClient } from "webdav/web"; -export type { WebDAVClient } from "webdav/web"; +import { AuthType, BufferLike, createClient } from "webdav"; +export type { WebDAVClient } from "webdav"; export const DEFAULT_WEBDAV_CONFIG = { address: "", @@ -234,7 +236,7 @@ export class WrappedWebdavClient { Depth: "infinity", }, responseType: "text", - }); + } as any); if (res.status === 403) { throw Error("not support Infinity, get 403"); } else { @@ -255,7 +257,7 @@ export class WrappedWebdavClient { Depth: "1", }, responseType: "text", - } + } as any ); testPassed = true; this.webdavConfig.depth = "auto_1"; diff --git a/webpack.config.js b/webpack.config.js index 03e8c62..cb6ee83 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -41,6 +41,12 @@ module.exports = { test: /\.svg?$/, type: "asset/source", }, + { + test: /\.m?js$/, + resolve: { + fullySpecified: false, // process/browser returns some errors before + }, + }, ], }, resolve: { @@ -55,7 +61,9 @@ module.exports = { // crypto: false, // domain: require.resolve("domain-browser"), // events: require.resolve("events"), + http: false, // http: require.resolve("stream-http"), + https: false, // https: require.resolve("https-browserify"), net: false, // os: require.resolve("os-browserify/browser"),