From 54c2b1c6db75aa55c2f3f6c4bbc09a03f3cc6791 Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Tue, 9 Jun 2026 05:59:02 +0100 Subject: [PATCH] reduce no-explicit-any --- esbuild.config.mjs | 37 ++++++++++++++++++- eslint.config.mjs | 3 +- src/LiveSyncBaseCore.ts | 1 + src/apps/cli/testdeno/test-daemon.ts | 6 ++- src/apps/cli/testdeno/test-decoupled-vault.ts | 35 ++---------------- .../testdeno/test-p2p-peers-local-relay.ts | 2 +- src/apps/cli/testdeno/test-p2p-sync.ts | 2 +- .../testdeno/test-p2p-three-nodes-conflict.ts | 2 +- src/apps/cli/testdeno/test-remote-commands.ts | 6 +-- src/common/KeyValueDB.ts | 4 +- src/common/KeyValueDBv2.ts | 4 +- src/common/PeriodicProcessor.ts | 4 +- src/common/reportTool.ts | 11 +++--- src/common/utils.ts | 28 +++++++------- src/features/ConfigSync/CmdConfigSync.ts | 20 ++++++---- .../HiddenFileSync/CmdHiddenFileSync.ts | 20 ++++++---- src/features/LiveSyncCommands.ts | 16 ++++---- .../CmdLocalDatabaseMainte.ts | 36 ++++++++++++++---- src/lib | 2 +- .../ObsidianStorageEventManagerAdapter.ts | 4 +- src/modules/AbstractModule.ts | 13 ++++--- src/modules/ModuleTypes.ts | 13 +++++-- src/modules/core/ModuleReplicator.ts | 4 +- src/modules/core/ReplicateResultProcessor.ts | 7 ++-- .../ModuleResolveMismatchedTweaks.ts | 6 +-- .../APILib/ObsHttpHandler.ts | 10 +++-- .../essentialObsidian/ModuleObsidianEvents.ts | 7 ++-- src/modules/extras/devUtil/testUtils.ts | 4 +- .../DocumentHistory/DocumentHistoryModal.ts | 8 ++-- src/modules/features/ModuleLog.ts | 4 +- .../SettingDialogue/LiveSyncSetting.ts | 3 +- .../ObsidianLiveSyncSettingTab.ts | 1 + .../features/SettingDialogue/PaneHatch.ts | 4 +- .../SettingDialogue/PaneRemoteConfig.ts | 6 +-- .../features/SettingDialogue/PaneSetup.ts | 4 +- .../features/SettingDialogue/SveltePanel.ts | 4 +- .../features/SettingDialogue/settingUtils.ts | 10 +++-- .../SettingDialogue/utilFixCouchDBSetting.ts | 4 +- .../SetupWizard/dialogs/utilCheckCouchDB.ts | 22 +++++++---- src/modules/services/ObsidianAPIService.ts | 4 +- src/serviceFeatures/redFlag.ts | 14 +++---- .../ObsidianTypeGuardAdapter.ts | 4 +- .../ObsidianVaultAdapter.ts | 1 + 43 files changed, 230 insertions(+), 170 deletions(-) diff --git a/esbuild.config.mjs b/esbuild.config.mjs index 4350fab..23b8fe9 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -19,11 +19,15 @@ const packageJson = JSON.parse(fs.readFileSync("./package.json") + ""); const updateInfo = JSON.stringify(fs.readFileSync("./updates.md") + ""); const PATHS_TEST_INSTALL = process.env?.PATHS_TEST_INSTALL || ""; -const PATH_TEST_INSTALL = PATHS_TEST_INSTALL.split(path.delimiter).map(p => p.trim()).filter(p => p.length); +const PATH_TEST_INSTALL = PATHS_TEST_INSTALL.split(path.delimiter) + .map((p) => p.trim()) + .filter((p) => p.length); if (PATH_TEST_INSTALL) { console.log(`Built files will be copied to ${PATH_TEST_INSTALL}`); } else { - console.log("Development build: You can install the plug-in to Obsidian for testing by exporting the PATHS_TEST_INSTALL environment variable with the paths to your vault plugins directories separated by your system path delimiter (':' on Unix, ';' on Windows)."); + console.log( + "Development build: You can install the plug-in to Obsidian for testing by exporting the PATHS_TEST_INSTALL environment variable with the paths to your vault plugins directories separated by your system path delimiter (':' on Unix, ';' on Windows)." + ); } const moduleAliasPlugin = { @@ -66,6 +70,34 @@ const moduleAliasPlugin = { }, }; +const removePragmaCommentsPlugin = { + name: "remove-pragma-comments", + setup(build) { + // Filter target extensions (e.g., JavaScript and TypeScript) + build.onLoad({ filter: /\.[jt]s?$/ }, async (args) => { + const source = await fs.promises.readFile(args.path, "utf8"); + + // Regex targeting both single-line and multi-line comments + // This regex looks for: + // - /* eslint ... */ (multi-line) + // const esLintPragmaRegexBlock = /\/\*[\s\S]*?eslint[\s\S]*?\*\/|([^\\:]|^)\/\/.*eslint.*$/gm; + // - // eslint-disable-next-line + let cleanedSource = source; + const tsIgnoreRegex = /\/\*\s*@ts-ignore\s*\*\/|([^\\:]|^)\/\/.*?@ts-ignore.*$/gm; + const esLintPragmaRegexLine = /([^\\:]|^)\/\/.*?eslint-.*$/gm; + const exps = [tsIgnoreRegex, esLintPragmaRegexLine]; + for (const exp of exps) { + cleanedSource = cleanedSource.replace(exp, "$1"); + } + + return { + contents: cleanedSource, + loader: args.path.endsWith("ts") ? "ts" : "js", + }; + }); + }, +}; + /** @type esbuild.Plugin[] */ const plugins = [ { @@ -177,6 +209,7 @@ const context = await esbuild.context({ preprocess: sveltePreprocess(), compilerOptions: { css: "injected", preserveComments: false }, }), + removePragmaCommentsPlugin, ...plugins, ], }); diff --git a/eslint.config.mjs b/eslint.config.mjs index 65f81a3..6544389 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -73,11 +73,12 @@ export default defineConfig([ "no-unused-labels": "off", "no-prototype-builtins": "off", "require-await": "off", + // -- TypeScript specific rules (Gradual adoption of stricter rules, currently set to 'warn' for a while). + "@typescript-eslint/no-explicit-any": "warn", // -- TypeScript specific rules // @typescript-eslint/no-unsafe-* rules and @typescript-eslint/no-explicit-any: // This project contains a lot of library-sh code where the use of `any` is often necessary and justified. // Rules is now set to 'off' for a while. - "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-unsafe-argument": "off", "@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/no-unsafe-member-access": "off", diff --git a/src/LiveSyncBaseCore.ts b/src/LiveSyncBaseCore.ts index 9a49451..a83c975 100644 --- a/src/LiveSyncBaseCore.ts +++ b/src/LiveSyncBaseCore.ts @@ -120,6 +120,7 @@ export class LiveSyncBaseCore< * @param constructor * @returns */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any getModule(constructor: new (...args: any[]) => T): T { for (const module of this.modules) { if (module.constructor === constructor) return module as T; diff --git a/src/apps/cli/testdeno/test-daemon.ts b/src/apps/cli/testdeno/test-daemon.ts index e960dfc..d5f16ff 100644 --- a/src/apps/cli/testdeno/test-daemon.ts +++ b/src/apps/cli/testdeno/test-daemon.ts @@ -109,7 +109,11 @@ Deno.test("daemon: ignore rules behaviour", async (t) => { await runCliOrFail(vaultDir, "--settings", settingsFile, "mirror"); const dbList = await runCliOrFail(vaultDir, "--settings", settingsFile, "ls"); - assertNotContains(dbList, "debug.log", "debug.log (ignored via .gitignore import) was unexpectedly synced to database"); + assertNotContains( + dbList, + "debug.log", + "debug.log (ignored via .gitignore import) was unexpectedly synced to database" + ); assertContains(dbList, "regular.md", "regular.md was not synced normally alongside .gitignore import rules"); console.log("[PASS] Case 3 verified successfully"); }); diff --git a/src/apps/cli/testdeno/test-decoupled-vault.ts b/src/apps/cli/testdeno/test-decoupled-vault.ts index 7e0f69a..f1a017f 100644 --- a/src/apps/cli/testdeno/test-decoupled-vault.ts +++ b/src/apps/cli/testdeno/test-decoupled-vault.ts @@ -46,9 +46,7 @@ Deno.test("decoupled database and vault", async () => { console.log("[INFO] applying CouchDB environment variables to settings"); await applyCouchdbSettings(settingsFile, uri, user, password, dbname); } else { - console.warn( - "[WARN] CouchDB environment variables are not fully set. Push and pull operations may fail." - ); + console.warn("[WARN] CouchDB environment variables are not fully set. Push and pull operations may fail."); await markSettingsConfigured(settingsFile); } @@ -59,29 +57,11 @@ Deno.test("decoupled database and vault", async () => { // 1. Test push command with decoupled vault directory console.log(`[INFO] push with decoupled vault -> ${REMOTE_PATH}`); - await runCliOrFail( - dbDir, - "--vault", - vaultDir, - "--settings", - settingsFile, - "push", - srcFile, - REMOTE_PATH - ); + await runCliOrFail(dbDir, "--vault", vaultDir, "--settings", settingsFile, "push", srcFile, REMOTE_PATH); // 2. Test pull command with decoupled vault directory console.log(`[INFO] pull with decoupled vault <- ${REMOTE_PATH}`); - await runCliOrFail( - dbDir, - "--vault", - vaultDir, - "--settings", - settingsFile, - "pull", - REMOTE_PATH, - pulledFile - ); + await runCliOrFail(dbDir, "--vault", vaultDir, "--settings", settingsFile, "pull", REMOTE_PATH, pulledFile); const pulled = await Deno.readTextFile(pulledFile); assertEquals(pulled, content, "push/pull roundtrip with decoupled vault content mismatch"); @@ -93,14 +73,7 @@ Deno.test("decoupled database and vault", async () => { // 4. Test mirror command with decoupled vault directory console.log("[INFO] mirror with decoupled vault"); - await runCliOrFail( - dbDir, - "--vault", - vaultDir, - "--settings", - settingsFile, - "mirror" - ); + await runCliOrFail(dbDir, "--vault", vaultDir, "--settings", settingsFile, "mirror"); const restoredFile = join(vaultDir, REMOTE_PATH); const restored = await Deno.readTextFile(restoredFile); diff --git a/src/apps/cli/testdeno/test-p2p-peers-local-relay.ts b/src/apps/cli/testdeno/test-p2p-peers-local-relay.ts index 36dbbf8..e8b162e 100644 --- a/src/apps/cli/testdeno/test-p2p-peers-local-relay.ts +++ b/src/apps/cli/testdeno/test-p2p-peers-local-relay.ts @@ -14,7 +14,7 @@ import { getOptimalLoopbackIp } from "./helpers/net.ts"; Deno.test("p2p-peers: discovers host through local relay", async () => { const loopbackIp = await getOptimalLoopbackIp(); const loopbackHost = loopbackIp === "::1" ? "[::1]" : loopbackIp; - + const relay = Deno.env.get("RELAY") ?? `ws://${loopbackHost}:4000/`; const roomId = Deno.env.get("ROOM_ID") ?? `room-${Date.now()}`; const passphrase = Deno.env.get("PASSPHRASE") ?? "test"; diff --git a/src/apps/cli/testdeno/test-p2p-sync.ts b/src/apps/cli/testdeno/test-p2p-sync.ts index 53cefda..e05c6ef 100644 --- a/src/apps/cli/testdeno/test-p2p-sync.ts +++ b/src/apps/cli/testdeno/test-p2p-sync.ts @@ -15,7 +15,7 @@ import { getOptimalLoopbackIp } from "./helpers/net.ts"; Deno.test("p2p-sync: discovers peer and completes sync", async () => { const loopbackIp = await getOptimalLoopbackIp(); const loopbackHost = loopbackIp === "::1" ? "[::1]" : loopbackIp; - + const relay = Deno.env.get("RELAY") ?? `ws://${loopbackHost}:4000/`; const roomId = Deno.env.get("ROOM_ID") ?? `room-${Date.now()}`; const passphrase = Deno.env.get("PASSPHRASE") ?? "test"; diff --git a/src/apps/cli/testdeno/test-p2p-three-nodes-conflict.ts b/src/apps/cli/testdeno/test-p2p-three-nodes-conflict.ts index 718367d..45eab2c 100644 --- a/src/apps/cli/testdeno/test-p2p-three-nodes-conflict.ts +++ b/src/apps/cli/testdeno/test-p2p-three-nodes-conflict.ts @@ -15,7 +15,7 @@ import { getOptimalLoopbackIp } from "./helpers/net.ts"; Deno.test("p2p: three nodes detect and resolve conflicts", async () => { const loopbackIp = await getOptimalLoopbackIp(); const loopbackHost = loopbackIp === "::1" ? "[::1]" : loopbackIp; - + const relay = Deno.env.get("RELAY") ?? `ws://${loopbackHost}:4000/`; const roomId = Deno.env.get("ROOM_ID") ?? `room-${Date.now()}`; const passphrase = Deno.env.get("PASSPHRASE") ?? "test"; diff --git a/src/apps/cli/testdeno/test-remote-commands.ts b/src/apps/cli/testdeno/test-remote-commands.ts index 9ed0afb..6040ab1 100644 --- a/src/apps/cli/testdeno/test-remote-commands.ts +++ b/src/apps/cli/testdeno/test-remote-commands.ts @@ -61,11 +61,7 @@ Deno.test("remote management commands", async () => { // 1. remote-status outputs valid JSON with CouchDB details console.log("[CASE] remote-status outputs valid JSON with CouchDB details"); const statusOutput = await runCliCombinedOrFail(vaultDir, "--settings", settingsFile, "remote-status"); - assertContains( - statusOutput, - `"db_name": "${dbname}"`, - "remote-status should return JSON containing db_name" - ); + assertContains(statusOutput, `"db_name": "${dbname}"`, "remote-status should return JSON containing db_name"); console.log("[PASS] remote-status verified"); // 2. lock-remote locks and verifies state diff --git a/src/common/KeyValueDB.ts b/src/common/KeyValueDB.ts index 3b02e07..a8ed78d 100644 --- a/src/common/KeyValueDB.ts +++ b/src/common/KeyValueDB.ts @@ -2,7 +2,7 @@ import { deleteDB, type IDBPDatabase, openDB } from "idb"; import type { KeyValueDatabase } from "../lib/src/interfaces/KeyValueDatabase.ts"; import { serialized } from "octagonal-wheels/concurrency/lock"; import { Logger } from "octagonal-wheels/common/logger"; -const databaseCache: { [key: string]: IDBPDatabase } = {}; +const databaseCache: { [key: string]: IDBPDatabase } = {}; export { OpenKeyValueDatabase } from "./KeyValueDBv2.ts"; export const _OpenKeyValueDatabase = async (dbKey: string): Promise => { @@ -11,7 +11,7 @@ export const _OpenKeyValueDatabase = async (dbKey: string): Promise | null = null; + let db: IDBPDatabase | null = null; const _openDB = () => { return serialized("keyvaluedb-" + dbKey, async () => { const dbInstance = await openDB(dbKey, 1, { diff --git a/src/common/KeyValueDBv2.ts b/src/common/KeyValueDBv2.ts index 66f0d46..a6ad077 100644 --- a/src/common/KeyValueDBv2.ts +++ b/src/common/KeyValueDBv2.ts @@ -28,7 +28,7 @@ export async function OpenKeyValueDatabase(dbKey: string): Promise> | null = null; + protected _dbPromise: Promise> | null = null; protected dbKey: string; protected storeKey: string; protected _isDestroyed: boolean = false; @@ -104,7 +104,7 @@ export class IDBKeyValueDatabase implements KeyValueDatabase { this.destroyedPromise = Promise.resolve(); } } - get DB(): Promise> { + get DB(): Promise> { if (this._isDestroyed) { return Promise.reject(new Error("Database is destroyed")); } diff --git a/src/common/PeriodicProcessor.ts b/src/common/PeriodicProcessor.ts index 04d92ba..d6c1f52 100644 --- a/src/common/PeriodicProcessor.ts +++ b/src/common/PeriodicProcessor.ts @@ -4,10 +4,10 @@ import { eventHub, EVENT_PLUGIN_UNLOADED } from "./events"; import type { NecessaryServices } from "@lib/interfaces/ServiceModule"; type PeriodicProcessorHost = NecessaryServices<"API" | "control", never>; export class PeriodicProcessor { - _process: () => Promise; + _process: () => Promise; _timer?: number = undefined; _core: PeriodicProcessorHost; - constructor(core: PeriodicProcessorHost, process: () => Promise) { + constructor(core: PeriodicProcessorHost, process: () => Promise) { // this._plugin = plugin; this._core = core; this._process = process; diff --git a/src/common/reportTool.ts b/src/common/reportTool.ts index 8eef539..e74dc2f 100644 --- a/src/common/reportTool.ts +++ b/src/common/reportTool.ts @@ -9,16 +9,15 @@ import { isCloudantURI } from "@lib/pouchdb/utils_couchdb"; import { compatGlobal } from "@lib/common/coreEnvFunctions"; import { manifestVersion, packageVersion } from "@lib/common/coreEnvVars"; import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore"; -function redactObject(obj: Record, dotted: string, redactedValue = "REDACTED") { +function redactObject(obj: Record, dotted: string, redactedValue = "REDACTED") { const keys = dotted.split("."); let current = obj; for (let i = 0; i < keys.length - 1; i++) { const key = keys[i]; if (!(key in current)) { - current[key] = {} as Record; + current[key] = {}; } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - current = current[key]; + current = current[key] as Record; } const lastKey = keys[keys.length - 1]; if (lastKey in current) { @@ -27,7 +26,7 @@ function redactObject(obj: Record, dotted: string, redactedValue = return obj; } export async function generateReport(settings: ObsidianLiveSyncSettings, core: LiveSyncBaseCore) { - let responseConfig: Record = {}; + let responseConfig: Record = {}; const REDACTED = "𝑅𝐸𝐷𝐴𝐢𝑇𝐸𝐷"; if (settings.remoteType == REMOTE_COUCHDB) { try { @@ -42,7 +41,7 @@ export async function generateReport(settings: ObsidianLiveSyncSettings, core: L undefined, customHeaders ); - responseConfig = r.json as Record; + responseConfig = r.json as Record; redactObject(responseConfig, "couch_httpd_auth.secret"); redactObject(responseConfig, "couch_httpd_auth.authentication_db"); redactObject(responseConfig, "couch_httpd_auth.authentication_redirect"); diff --git a/src/common/utils.ts b/src/common/utils.ts index 829d608..f995127 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -72,7 +72,7 @@ import { } from "@lib/common/typeUtils.ts"; export { isInternalFile, getPathFromUXFileInfo, getStoragePathFromUXFileInfo, getDatabasePathFromUXFileInfo }; -const memos: { [key: string]: any } = {}; +const memos: Record = {}; export function memoObject(key: string, obj: T): T { memos[key] = obj; return memos[key] as T; @@ -87,7 +87,7 @@ export async function memoIfNotExist(key: string, func: () => T | Promise) } export function retrieveMemoObject(key: string): T | false { if (key in memos) { - return memos[key]; + return memos[key] as T; } else { return false; } @@ -128,7 +128,7 @@ export const _requestToCouchDBFetch = async ( username: string, password: string, path?: string, - body?: any, + body?: unknown, method?: string ) => { const utf8str = String.fromCharCode.apply(null, [...writeString(`${username}:${password}`)]); @@ -154,7 +154,7 @@ export const _requestToCouchDB = async ( credentials: CouchDBCredentials, origin: string, path?: string, - body?: any, + body?: unknown, method?: string, customHeaders?: Record ) => { @@ -263,27 +263,27 @@ export function compareFileFreshness( const _cached = new Map< string, { - value: any; - context: Map; + value: unknown; + context: Map; } >(); export type MemoOption = { key: string; forceUpdate?: boolean; - validator?: (context: Map) => boolean; + validator?: (context: Map) => boolean; }; export function useMemo( { key, forceUpdate, validator }: MemoOption, - updateFunc: (context: Map, prev: T) => T + updateFunc: (context: Map, prev: T) => T ): T { const cached = _cached.get(key); - const context = cached?.context || new Map(); + const context = cached?.context || new Map(); if (cached && !forceUpdate && (!validator || (validator && !validator(context)))) { - return cached.value; + return cached.value as T; } - const value = updateFunc(context, cached?.value); + const value = updateFunc(context, cached?.value as T); if (value !== cached?.value) { _cached.set(key, { value, context }); } @@ -294,7 +294,7 @@ export function useMemo( const _staticObj = new Map< string, { - value: any; + value: unknown; } >(); @@ -306,7 +306,7 @@ export function useStatic(key: string, initial?: T) { // } const obj = _staticObj.get(key); if (obj !== undefined) { - return obj; + return obj as { value: T }; } else { // let buf = initial; const obj = { @@ -390,7 +390,7 @@ export async function autosaveCache(db: KeyValueDatabase, mapKey: string): }; } -export function onlyInNTimes(n: number, proc: (progress: number) => any) { +export function onlyInNTimes(n: number, proc: (progress: number) => unknown) { let counter = 0; return function () { if (counter++ % n == 0) { diff --git a/src/features/ConfigSync/CmdConfigSync.ts b/src/features/ConfigSync/CmdConfigSync.ts index 585ef5c..fac8933 100644 --- a/src/features/ConfigSync/CmdConfigSync.ts +++ b/src/features/ConfigSync/CmdConfigSync.ts @@ -1100,10 +1100,16 @@ export class ConfigSync extends LiveSyncCommands { await delay(100); this._log(`Config ${data.displayName || data.name} has been applied`, LOG_LEVEL_NOTICE); if (data.category == "PLUGIN_DATA" || data.category == "PLUGIN_MAIN") { - //@ts-ignore - const manifests = Object.values(this.app.plugins.manifests) as any as PluginManifest[]; - //@ts-ignore - const enabledPlugins = this.app.plugins.enabledPlugins as Set; + const appWithPlugins = this.app as unknown as { + plugins: { + manifests: Record; + enabledPlugins: Set; + unloadPlugin(id: string): Promise; + loadPlugin(id: string): Promise; + }; + }; + const manifests = Object.values(appWithPlugins.plugins.manifests); + const enabledPlugins = appWithPlugins.plugins.enabledPlugins; const pluginManifest = manifests.find( (manifest) => enabledPlugins.has(manifest.id) && manifest.dir == `${baseDir}/plugins/${data.name}` ); @@ -1113,10 +1119,8 @@ export class ConfigSync extends LiveSyncCommands { LOG_LEVEL_NOTICE, "plugin-reload-" + pluginManifest.id ); - // @ts-ignore - await this.app.plugins.unloadPlugin(pluginManifest.id); - // @ts-ignore - await this.app.plugins.loadPlugin(pluginManifest.id); + await appWithPlugins.plugins.unloadPlugin(pluginManifest.id); + await appWithPlugins.plugins.loadPlugin(pluginManifest.id); this._log( `Plugin reloaded: ${pluginManifest.name}`, LOG_LEVEL_NOTICE, diff --git a/src/features/HiddenFileSync/CmdHiddenFileSync.ts b/src/features/HiddenFileSync/CmdHiddenFileSync.ts index 3c086d6..d115e02 100644 --- a/src/features/HiddenFileSync/CmdHiddenFileSync.ts +++ b/src/features/HiddenFileSync/CmdHiddenFileSync.ts @@ -1224,10 +1224,16 @@ Offline Changed files: ${files.length}`; const updatedFolders = [...this.queuedNotificationFiles]; this.queuedNotificationFiles.clear(); try { - //@ts-ignore - const manifests = Object.values(this.app.plugins.manifests) as any as PluginManifest[]; - //@ts-ignore - const enabledPlugins = this.app.plugins.enabledPlugins as Set; + const appWithPlugins = this.app as unknown as { + plugins: { + manifests: Record; + enabledPlugins: Set; + unloadPlugin(id: string): Promise; + loadPlugin(id: string): Promise; + }; + }; + const manifests = Object.values(appWithPlugins.plugins.manifests); + const enabledPlugins = appWithPlugins.plugins.enabledPlugins; const enabledPluginManifests = manifests.filter((e) => enabledPlugins.has(e.id)); const modifiedManifests = enabledPluginManifests.filter((e) => updatedFolders.indexOf(e?.dir ?? "") >= 0); for (const manifest of modifiedManifests) { @@ -1246,10 +1252,8 @@ Offline Changed files: ${files.length}`; LOG_LEVEL_NOTICE, "plugin-reload-" + updatePluginId ); - // @ts-ignore - await this.app.plugins.unloadPlugin(updatePluginId); - // @ts-ignore - await this.app.plugins.loadPlugin(updatePluginId); + await appWithPlugins.plugins.unloadPlugin(updatePluginId); + await appWithPlugins.plugins.loadPlugin(updatePluginId); this._log( `Plugin reloaded: ${updatePluginName}`, LOG_LEVEL_NOTICE, diff --git a/src/features/LiveSyncCommands.ts b/src/features/LiveSyncCommands.ts index 2f79fc9..a84559b 100644 --- a/src/features/LiveSyncCommands.ts +++ b/src/features/LiveSyncCommands.ts @@ -67,25 +67,25 @@ export abstract class LiveSyncCommands { _log: ReturnType; - _verbose = (msg: any, key?: string) => { + _verbose = (msg: unknown, key?: string) => { this._log(msg, LOG_LEVEL_VERBOSE, key); }; - _info = (msg: any, key?: string) => { + _info = (msg: unknown, key?: string) => { this._log(msg, LOG_LEVEL_INFO, key); }; - _notice = (msg: any, key?: string) => { + _notice = (msg: unknown, key?: string) => { this._log(msg, LOG_LEVEL_NOTICE, key); }; _progress = (prefix: string = "", level: LOG_LEVEL = LOG_LEVEL_NOTICE) => { const key = `keepalive-progress-${noticeIndex++}`; return { - log: (msg: any) => { - this._log(prefix + msg, level, key); + log: (msg: unknown) => { + this._log(prefix + String(msg), level, key); }, - once: (msg: any) => { - this._log(prefix + msg, level); + once: (msg: unknown) => { + this._log(prefix + String(msg), level); }, done: (msg: string = "Done") => { this._log(prefix + msg + MARK_DONE, level, key); @@ -93,7 +93,7 @@ export abstract class LiveSyncCommands { }; }; - _debug = (msg: any, key?: string) => { + _debug = (msg: unknown, key?: string) => { this._log(msg, LOG_LEVEL_VERBOSE, key); }; diff --git a/src/features/LocalDatabaseMainte/CmdLocalDatabaseMainte.ts b/src/features/LocalDatabaseMainte/CmdLocalDatabaseMainte.ts index 54eb7aa..ac4b964 100644 --- a/src/features/LocalDatabaseMainte/CmdLocalDatabaseMainte.ts +++ b/src/features/LocalDatabaseMainte/CmdLocalDatabaseMainte.ts @@ -17,6 +17,7 @@ import { arrayToChunkedArray } from "octagonal-wheels/collection"; import { EVENT_ANALYSE_DB_USAGE, EVENT_REQUEST_PERFORM_GC_V3, eventHub } from "@/common/events"; import type { LiveSyncCouchDBReplicator } from "@/lib/src/replication/couchdb/LiveSyncReplicator"; import { delay } from "@/lib/src/common/utils"; +import { isNotFoundError } from "@lib/common/utils.doc.ts"; // import { _requestToCouchDB } from "@/common/utils"; const DB_KEY_SEQ = "gc-seq"; const DB_KEY_CHUNK_SET = "chunk-set"; @@ -393,8 +394,8 @@ Note: **Make sure to synchronise all devices before deletion.** await processDoc(oldDoc, false); } } - } catch (ex) { - if ((ex as any)?.status == 404) { + } catch (ex: unknown) { + if (ex && typeof ex === "object" && isNotFoundError(ex)) { this._log(`No revisions found for ${doc._id}`, LOG_LEVEL_VERBOSE); } else { this._log(`Error finding revisions for ${doc._id}`); @@ -473,15 +474,23 @@ Are you ready to delete unused chunks?`; keys: [...unusedSet], include_docs: true, }); + interface PouchDBRow { + id: string; + key: string; + value: { rev: string; deleted?: boolean }; + doc?: EntryDoc; + } for (const chunk of deleteChunks.rows) { - if ((chunk as any)?.value?.deleted) { - chunkSet.delete(chunk.key as DocumentID); + const c = chunk as unknown as PouchDBRow; + if (c.value?.deleted) { + chunkSet.delete(c.key as DocumentID); } } const deleteDocs = deleteChunks.rows - .filter((e) => "doc" in e) + .map((e) => e as unknown as PouchDBRow) + .filter((e) => e.doc != null) .map((e) => ({ - ...(e as any).doc!, + ...e.doc!, _deleted: true, })); @@ -625,8 +634,19 @@ Success: ${successCount}, Errored: ${errored}`; } } } + interface DatabaseAnalysisResultItem { + title: string; + path: string; + rev: string; + revHash: string; + id?: string; + uniqueChunkCount: number; + sharedChunkCount: number; + uniqueChunkSize: number; + sharedChunkSize: number; + } // Prepare results - const result = []; + const result: DatabaseAnalysisResultItem[] = []; // Calculate total size of chunks in the given set. const getTotalSize = (ids: Set) => { return [...ids].reduce((acc, chunkId) => { @@ -698,7 +718,7 @@ Success: ${successCount}, Errored: ${errored}`; sharedChunkCount: 0, uniqueChunkSize: orphanChunkSize, sharedChunkSize: 0, - } as any); + }); const csvSrc = result.map((e) => { return [ diff --git a/src/lib b/src/lib index 53804cb..7c43d69 160000 --- a/src/lib +++ b/src/lib @@ -1 +1 @@ -Subproject commit 53804cbaec7fed9591321e7fbe6dcc9092e51017 +Subproject commit 7c43d69c6566408cd8a2d466938c708fe755ee23 diff --git a/src/managers/ObsidianStorageEventManagerAdapter.ts b/src/managers/ObsidianStorageEventManagerAdapter.ts index 5645ac6..6c5534a 100644 --- a/src/managers/ObsidianStorageEventManagerAdapter.ts +++ b/src/managers/ObsidianStorageEventManagerAdapter.ts @@ -20,7 +20,7 @@ import { InternalFileToUXFileInfoStub, TFileToUXFileInfoStub } from "@/modules/c * Obsidian-specific type guard adapter */ class ObsidianTypeGuardAdapter implements IStorageEventTypeGuardAdapter { - isFile(file: any): file is TFile { + isFile(file: unknown): file is TFile { if (file instanceof TFile) { return true; } @@ -30,7 +30,7 @@ class ObsidianTypeGuardAdapter implements IStorageEventTypeGuardAdapter Promise) { + async _test(key: string, process: () => Promise) { this._log(`Testing ${key}`, LOG_LEVEL_VERBOSE); try { const ret = await process(); if (ret !== true) { - this.addTestResult(key, false, ret.toString()); - return this.testFail(`${key} failed: ${ret}`); + this.addTestResult(key, false, String(ret)); + return this.testFail(`${key} failed: ${String(ret)}`); } this.addTestResult(key, true, ""); - } catch (ex: any) { - this.addTestResult(key, false, "Failed by Exception", ex.toString()); - return this.testFail(`${key} failed: ${ex}`); + } catch (ex) { + const exStr = String(ex); + this.addTestResult(key, false, "Failed by Exception", exStr); + return this.testFail(`${key} failed: ${exStr}`); } return this.testDone(); } diff --git a/src/modules/ModuleTypes.ts b/src/modules/ModuleTypes.ts index 3151b51..6727299 100644 --- a/src/modules/ModuleTypes.ts +++ b/src/modules/ModuleTypes.ts @@ -7,7 +7,8 @@ export type OverridableFunctionsKeys = { export type ChainableExecuteFunction = { [K in keyof T as K extends `$${string}` - ? T[K] extends (...args: any) => ChainableFunctionResult + ? // eslint-disable-next-line @typescript-eslint/no-explicit-any + T[K] extends (...args: any) => ChainableFunctionResult ? K : never : never]: T[K]; @@ -26,26 +27,30 @@ export type ChainableFunctionResultOrAll = Promise = { [K in keyof T as K extends `$all${string}` - ? T[K] extends (...args: any[]) => ChainableFunctionResultOrAll + ? // eslint-disable-next-line @typescript-eslint/no-explicit-any + T[K] extends (...args: any[]) => ChainableFunctionResultOrAll ? K : never : never]: T[K]; }; type EveryExecuteFunction = { [K in keyof T as K extends `$every${string}` - ? T[K] extends (...args: any[]) => ChainableFunctionResult + ? // eslint-disable-next-line @typescript-eslint/no-explicit-any + T[K] extends (...args: any[]) => ChainableFunctionResult ? K : never : never]: T[K]; }; type AnyExecuteFunction = { [K in keyof T as K extends `$any${string}` - ? T[K] extends (...args: any[]) => ChainableFunctionResult + ? // eslint-disable-next-line @typescript-eslint/no-explicit-any + T[K] extends (...args: any[]) => ChainableFunctionResult ? K : never : never]: T[K]; }; type InjectableFunction = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any [K in keyof T as K extends `$$${string}` ? (T[K] extends (...args: any[]) => any ? K : never) : never]: T[K]; }; export type AllExecuteProps = AllExecuteFunction; diff --git a/src/modules/core/ModuleReplicator.ts b/src/modules/core/ModuleReplicator.ts index ddc59d0..6ab097b 100644 --- a/src/modules/core/ModuleReplicator.ts +++ b/src/modules/core/ModuleReplicator.ts @@ -21,7 +21,7 @@ import { MARK_LOG_NETWORK_ERROR } from "@lib/services/lib/logUtils"; function isOnlineAndCanReplicate( errorManager: UnresolvedErrorManager, - host: NecessaryServices<"API", any>, + host: NecessaryServices<"API", never>, showMessage: boolean ): Promise { const errorMessage = "Network is offline"; @@ -34,7 +34,7 @@ function isOnlineAndCanReplicate( } async function canReplicateWithPBKDF2( errorManager: UnresolvedErrorManager, - host: NecessaryServices<"replicator" | "setting", any>, + host: NecessaryServices<"replicator" | "setting", never>, showMessage: boolean ): Promise { const currentSettings = host.services.setting.currentSettings(); diff --git a/src/modules/core/ReplicateResultProcessor.ts b/src/modules/core/ReplicateResultProcessor.ts index fb35a5b..d8c74b4 100644 --- a/src/modules/core/ReplicateResultProcessor.ts +++ b/src/modules/core/ReplicateResultProcessor.ts @@ -18,6 +18,7 @@ import { type LOG_LEVEL, } from "@lib/common/logger"; import { fireAndForget, isAnyNote, throttle } from "@lib/common/utils"; +import { isNotFoundError } from "@lib/common/utils.doc.ts"; import { Semaphore } from "octagonal-wheels/concurrency/semaphore_v2"; import { serialized } from "octagonal-wheels/concurrency/lock"; import type { ReactiveSource } from "octagonal-wheels/dataobject/reactive_v2"; @@ -39,7 +40,7 @@ export class ReplicateResultProcessor { private log(message: string, level: LOG_LEVEL = LOG_LEVEL_INFO) { Logger(`[ReplicateResultProcessor] ${message}`, level); } - private logError(e: any) { + private logError(e: unknown) { Logger(e, LOG_LEVEL_VERBOSE); } private replicator: ModuleReplicator; @@ -466,8 +467,8 @@ export class ReplicateResultProcessor { return false; // This means that the document already processed (While no conflict existed). } return true; // This mostly should not happen, but we have to process it just in case. - } catch (e: any) { - if ("status" in e && e.status == 404) { + } catch (e: unknown) { + if (e && typeof e === "object" && isNotFoundError(e)) { // getRaw failed due to not existing, it may not be happened normally especially on replication. // If the process caused by some other reason, we **probably** have to process it. // Note that this is not a common case. diff --git a/src/modules/coreFeatures/ModuleResolveMismatchedTweaks.ts b/src/modules/coreFeatures/ModuleResolveMismatchedTweaks.ts index 4c95bbf..e816b93 100644 --- a/src/modules/coreFeatures/ModuleResolveMismatchedTweaks.ts +++ b/src/modules/coreFeatures/ModuleResolveMismatchedTweaks.ts @@ -18,14 +18,14 @@ import type { InjectableServiceHub } from "../../lib/src/services/InjectableServ import type { LiveSyncCore } from "../../main.ts"; import { REMOTE_P2P } from "@lib/common/models/setting.const.ts"; -function valueToString(value: any) { +function valueToString(value: unknown) { if (typeof value === "boolean") { return value ? "true" : "false"; } - if (typeof value === "object") { + if (typeof value === "object" && value !== null) { return JSON.stringify(value); } - return `${value}`; + return String(value); } export class ModuleResolvingMismatchedTweaks extends AbstractModule { diff --git a/src/modules/essentialObsidian/APILib/ObsHttpHandler.ts b/src/modules/essentialObsidian/APILib/ObsHttpHandler.ts index ef5614c..b51604a 100644 --- a/src/modules/essentialObsidian/APILib/ObsHttpHandler.ts +++ b/src/modules/essentialObsidian/APILib/ObsHttpHandler.ts @@ -68,9 +68,13 @@ export class ObsHttpHandler extends FetchHttpHandler { contentType = transformedHeaders["content-type"]; } - let transformedBody: any = body; - if (ArrayBuffer.isView(body)) { - transformedBody = new Uint8Array(body.buffer).buffer; + let transformedBody: string | ArrayBuffer | undefined = undefined; + if (typeof body === "string" || body instanceof ArrayBuffer) { + transformedBody = body; + } else if (ArrayBuffer.isView(body)) { + transformedBody = body.buffer as ArrayBuffer; + } else if (body != null) { + transformedBody = body as string | ArrayBuffer; } const param: RequestUrlParam = { diff --git a/src/modules/essentialObsidian/ModuleObsidianEvents.ts b/src/modules/essentialObsidian/ModuleObsidianEvents.ts index 638b960..3928f92 100644 --- a/src/modules/essentialObsidian/ModuleObsidianEvents.ts +++ b/src/modules/essentialObsidian/ModuleObsidianEvents.ts @@ -36,13 +36,14 @@ export class ModuleObsidianEvents extends AbstractObsidianModule { this.services.appLifecycle.performRestart(); } - initialCallback: any; + initialCallback: (() => unknown) | undefined; swapSaveCommand() { this._log("Modifying callback of the save command", LOG_LEVEL_VERBOSE); - const saveCommandDefinition = (this.app as any).commands?.commands?.["editor:save-file"]; + const app = this.app as unknown as { commands?: { commands?: Record unknown }> } }; + const saveCommandDefinition = app.commands?.commands?.["editor:save-file"]; const save = saveCommandDefinition?.callback; - if (typeof save === "function") { + if (typeof save === "function" && saveCommandDefinition) { this.initialCallback = save; saveCommandDefinition.callback = () => { scheduleTask("syncOnEditorSave", 250, () => { diff --git a/src/modules/extras/devUtil/testUtils.ts b/src/modules/extras/devUtil/testUtils.ts index 6d1e86e..3801a4e 100644 --- a/src/modules/extras/devUtil/testUtils.ts +++ b/src/modules/extras/devUtil/testUtils.ts @@ -6,7 +6,7 @@ let plugin: ObsidianLiveSyncPlugin; export function enableTestFunction(plugin_: ObsidianLiveSyncPlugin) { plugin = plugin_; } -export function addDebugFileLog(message: any, stackLog = false) { +export function addDebugFileLog(message: unknown, stackLog = false) { fireAndForget( serialized("debug-log", async () => { const now = new Date(); @@ -16,7 +16,7 @@ export function addDebugFileLog(message: any, stackLog = false) { // const messageContent = typeof message == "string" ? message : message instanceof Error ? `${message.name}:${message.message}` : JSON.stringify(message, null, 2); const timestamp = now.toLocaleString(); const timestampEpoch = now; - let out = { timestamp: timestamp, epoch: timestampEpoch } as Record; + let out = { timestamp: timestamp, epoch: timestampEpoch } as Record; if (message instanceof Error) { // debugger; // console.dir(message.stack); diff --git a/src/modules/features/DocumentHistory/DocumentHistoryModal.ts b/src/modules/features/DocumentHistory/DocumentHistoryModal.ts index 5063fa7..72dc8f8 100644 --- a/src/modules/features/DocumentHistory/DocumentHistoryModal.ts +++ b/src/modules/features/DocumentHistory/DocumentHistoryModal.ts @@ -139,7 +139,7 @@ export class DocumentHistoryModal extends Modal { this.range.value = `${this.revs_info.length - 1 - rIndex}`; } } - const index = this.revs_info.length - 1 - (this.range.value as any) / 1; + const index = this.revs_info.length - 1 - Number(this.range.value); const rev = this.revs_info[index]; await this.showExactRev(rev.rev); } @@ -251,7 +251,7 @@ export class DocumentHistoryModal extends Modal { } let rendered = false; if (this.showDiff) { - const prevRevIdx = this.revs_info.length - 1 - ((this.range.value as any) / 1 - 1); + const prevRevIdx = this.revs_info.length - 1 - (Number(this.range.value) - 1); if (prevRevIdx >= 0 && prevRevIdx < this.revs_info.length) { const oldRev = this.revs_info[prevRevIdx].rev; const w2 = await db.getDBEntry(this.file, { rev: oldRev }, false, false, true); @@ -550,7 +550,7 @@ export class DocumentHistoryModal extends Modal { if (this.showDiff) { checkbox.checked = true; } - checkbox.addEventListener("input", (evt: any) => { + checkbox.addEventListener("input", (evt) => { this.showDiff = checkbox.checked; this.app.saveLocalStorage("ols-history-highlightdiff", this.showDiff == true ? "1" : null); this.updateDiffNavVisibility(); @@ -565,7 +565,7 @@ export class DocumentHistoryModal extends Modal { if (this.diffOnly) { checkbox.checked = true; } - checkbox.addEventListener("input", (evt: any) => { + checkbox.addEventListener("input", (evt) => { this.diffOnly = checkbox.checked; this.app.saveLocalStorage("ols-history-diffonly", this.diffOnly == true ? "1" : null); void scheduleOnceIfDuplicated("loadRevs", () => this.loadRevs()); diff --git a/src/modules/features/ModuleLog.ts b/src/modules/features/ModuleLog.ts index 062549a..8bd205e 100644 --- a/src/modules/features/ModuleLog.ts +++ b/src/modules/features/ModuleLog.ts @@ -48,7 +48,7 @@ import { generateReport } from "@/common/reportTool.ts"; // DI the log again. const recentLogEntries = reactiveSource([]); -const globalLogFunction = (message: any, level?: number, key?: string) => { +const globalLogFunction = (message: unknown, level?: number, key?: string) => { const messageX = message instanceof Error ? new LiveSyncError("[Error Logged]: " + message.message, { cause: message }) @@ -501,7 +501,7 @@ ${stringifyYaml(info)} }) ); } - __addLog(message: any, level: LOG_LEVEL = LOG_LEVEL_INFO, key = ""): void { + __addLog(message: unknown, level: LOG_LEVEL = LOG_LEVEL_INFO, key = ""): void { if (level == LOG_LEVEL_DEBUG && !showDebugLog) { return; } diff --git a/src/modules/features/SettingDialogue/LiveSyncSetting.ts b/src/modules/features/SettingDialogue/LiveSyncSetting.ts index 894916e..995e3b2 100644 --- a/src/modules/features/SettingDialogue/LiveSyncSetting.ts +++ b/src/modules/features/SettingDialogue/LiveSyncSetting.ts @@ -35,7 +35,7 @@ export class LiveSyncSetting extends Setting { hasPassword: boolean = false; invalidateValue?: () => void; - setValue?: (value: any) => void; + setValue?: (value: unknown) => void; constructor(containerEl: HTMLElement) { super(containerEl); LiveSyncSetting.env.settingComponents.push(this); @@ -102,6 +102,7 @@ export class LiveSyncSetting extends Setting { } return conf; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any autoWireComponent(component: ValueComponent, conf?: ConfigurationItem, opt?: AutoWireOption) { this.placeHolderBuf = conf?.placeHolder || opt?.placeHolder || ""; if (conf?.level == LEVEL_ADVANCED) { diff --git a/src/modules/features/SettingDialogue/ObsidianLiveSyncSettingTab.ts b/src/modules/features/SettingDialogue/ObsidianLiveSyncSettingTab.ts index c06dcfe..8d547cb 100644 --- a/src/modules/features/SettingDialogue/ObsidianLiveSyncSettingTab.ts +++ b/src/modules/features/SettingDialogue/ObsidianLiveSyncSettingTab.ts @@ -287,6 +287,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { // UI Element Wrapper --> settingComponents = [] as Setting[]; controlledElementFunc = [] as UpdateFunction[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any onSavedHandlers = [] as OnSavedHandler[]; inWizard: boolean = false; diff --git a/src/modules/features/SettingDialogue/PaneHatch.ts b/src/modules/features/SettingDialogue/PaneHatch.ts index 18c878f..816f9b8 100644 --- a/src/modules/features/SettingDialogue/PaneHatch.ts +++ b/src/modules/features/SettingDialogue/PaneHatch.ts @@ -442,7 +442,9 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, ...e.doc, _deleted: true, })); - const r = await this.core.localDatabase.bulkDocsRaw(newData as any[]); + const r = await this.core.localDatabase.bulkDocsRaw( + newData as Parameters[0] + ); // Do not care about the result. Logger( `${r.length} items have been removed, to confirm how many items are left, please perform it again.`, diff --git a/src/modules/features/SettingDialogue/PaneRemoteConfig.ts b/src/modules/features/SettingDialogue/PaneRemoteConfig.ts index 8fb94e9..c117470 100644 --- a/src/modules/features/SettingDialogue/PaneRemoteConfig.ts +++ b/src/modules/features/SettingDialogue/PaneRemoteConfig.ts @@ -7,7 +7,7 @@ import { type ObsidianLiveSyncSettings, LOG_LEVEL_VERBOSE, } from "../../../lib/src/common/types.ts"; -import { Menu } from "@/deps.ts"; +import { Menu, ButtonComponent } from "@/deps.ts"; import { $msg } from "../../../lib/src/common/i18n.ts"; import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts"; import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts"; @@ -39,7 +39,7 @@ function getSettingsFromEditingSettings(editingSettings: AllSettings): ObsidianL const workObj = { ...editingSettings } as ObsidianLiveSyncSettings; const keys = Object.keys(OnDialogSettingsDefault); for (const k of keys) { - delete (workObj as any)[k]; + delete (workObj as unknown as Record)[k]; } return workObj; } @@ -72,7 +72,7 @@ function serializeRemoteConfiguration(settings: ObsidianLiveSyncSettings): strin return ConnectionStringParser.serialize({ type: "couchdb", settings }); } -function setEmojiButton(button: any, emoji: string, tooltip: string) { +function setEmojiButton(button: ButtonComponent, emoji: string, tooltip: string) { button.setButtonText(emoji); button.setTooltip(tooltip, { delay: 10, placement: "top" }); // button.buttonEl.addClass("clickable-icon"); diff --git a/src/modules/features/SettingDialogue/PaneSetup.ts b/src/modules/features/SettingDialogue/PaneSetup.ts index 4e365c9..1d50fd9 100644 --- a/src/modules/features/SettingDialogue/PaneSetup.ts +++ b/src/modules/features/SettingDialogue/PaneSetup.ts @@ -145,8 +145,8 @@ export function paneSetup( let remoteTroubleShootMDSrc = ""; try { remoteTroubleShootMDSrc = await request(`${rawRepoURI}${basePath}/${filename}`); - } catch (ex: any) { - remoteTroubleShootMDSrc = `${$msg("obsidianLiveSyncSettingTab.logErrorOccurred")}\n${ex.toString()}`; + } catch (ex) { + remoteTroubleShootMDSrc = `${$msg("obsidianLiveSyncSettingTab.logErrorOccurred")}\n${String(ex)}`; } const remoteTroubleShootMD = remoteTroubleShootMDSrc.replace( /\((.*?(.png)|(.jpg))\)/g, diff --git a/src/modules/features/SettingDialogue/SveltePanel.ts b/src/modules/features/SettingDialogue/SveltePanel.ts index 9dc13a1..09f312b 100644 --- a/src/modules/features/SettingDialogue/SveltePanel.ts +++ b/src/modules/features/SettingDialogue/SveltePanel.ts @@ -5,7 +5,7 @@ import { type Writable, writable, get } from "svelte/store"; * Props passed to Svelte panels, containing a writable port * to communicate with the panel */ -export type SveltePanelProps = { +export type SveltePanelProps = { port: Writable; }; @@ -13,7 +13,7 @@ export type SveltePanelProps = { * A class to manage a Svelte panel within Obsidian * Especially useful for settings panels */ -export class SveltePanel { +export class SveltePanel { private _mountedComponent: ReturnType; private _componentValue = writable(undefined); /** diff --git a/src/modules/features/SettingDialogue/settingUtils.ts b/src/modules/features/SettingDialogue/settingUtils.ts index 847ebc0..d54c81b 100644 --- a/src/modules/features/SettingDialogue/settingUtils.ts +++ b/src/modules/features/SettingDialogue/settingUtils.ts @@ -13,6 +13,8 @@ import { } from "../../../lib/src/common/utils"; import { getConfig, type AllSettingItemKey } from "./settingConstants"; import { LOG_LEVEL_NOTICE, Logger } from "octagonal-wheels/common/logger"; +import { isNotFoundError } from "@lib/common/utils.doc.ts"; +import { LiveSyncError } from "@lib/common/LSError.ts"; /** * Generates a summary of P2P configuration settings @@ -95,13 +97,13 @@ export function getSummaryFromPartialSettings(setting: Partial }; +export type ResultOk = { message: string; result: "ok"; value?: unknown }; +export type ResultError = { + message: string; + result: "error"; + value?: string; + fixMessage: string; + fix(): Promise; +}; export type ConfigCheckResult = ResultOk | ResultError | ResultMessage | ResultErrorMessage; /** * Compares two version strings to determine if the baseVersion is greater than or equal to the version. @@ -35,7 +41,7 @@ function isGreaterThanOrEqual(baseVersion: string, version: string) { * @param value setting value to update * @returns true if the update was successful, false otherwise */ -async function updateRemoteSetting(setting: ObsidianLiveSyncSettings, key: string, value: any) { +async function updateRemoteSetting(setting: ObsidianLiveSyncSettings, key: string, value: string) { const customHeaders = parseHeaderValues(setting.couchDB_CustomHeaders); const credential = generateCredentialObject(setting); const res = await requestToCouchDBWithCredentials( @@ -64,17 +70,17 @@ export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) => const addMessage = (msg: string, classes: string[] = []) => { result.push({ message: msg, classes }); }; - const addSuccess = (msg: string, value?: any) => { + const addSuccess = (msg: string, value?: unknown) => { result.push({ message: msg, result: "ok", value }); }; - const _addError = (message: string, fixMessage: string, fix: () => Promise, value?: any) => { + const _addError = (message: string, fixMessage: string, fix: () => Promise, value?: string) => { result.push({ message, result: "error", fixMessage, fix, value }); }; const addErrorMessage = (msg: string, classes: string[] = []) => { result.push({ message: msg, result: "error", classes }); }; - const addError = (message: string, fixMessage: string, key: string, expected: any) => { + const addError = (message: string, fixMessage: string, key: string, expected: string) => { _addError(message, fixMessage, async () => { await updateRemoteSetting(editingSettings, key, expected); }); @@ -279,8 +285,8 @@ export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) => addMessage($msg("obsidianLiveSyncSettingTab.msgDone"), ["ob-btn-config-head"]); addMessage($msg("obsidianLiveSyncSettingTab.msgConnectionProxyNote"), ["ob-btn-config-info"]); addMessage($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone")); - } catch (ex: any) { - if (ex?.status == 401) { + } catch (ex) { + if (ex && typeof ex === "object" && "status" in ex && ex.status == 401) { addErrorMessage($msg("obsidianLiveSyncSettingTab.errAccessForbidden")); addErrorMessage($msg("obsidianLiveSyncSettingTab.errCannotContinueTest")); addMessage($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone")); diff --git a/src/modules/services/ObsidianAPIService.ts b/src/modules/services/ObsidianAPIService.ts index 2ac8d76..6185077 100644 --- a/src/modules/services/ObsidianAPIService.ts +++ b/src/modules/services/ObsidianAPIService.ts @@ -125,11 +125,11 @@ export class ObsidianAPIService extends InjectableAPIService any): HTMLElement { + addRibbonIcon(icon: string, title: string, callback: (evt: MouseEvent) => void): HTMLElement { return this.context.plugin.addRibbonIcon(icon, title, callback); } - registerProtocolHandler(action: string, handler: (params: Record) => any): void { + registerProtocolHandler(action: string, handler: (params: Record) => void): void { return this.context.plugin.registerObsidianProtocolHandler(action, handler); } diff --git a/src/serviceFeatures/redFlag.ts b/src/serviceFeatures/redFlag.ts index 6f0af05..aeee690 100644 --- a/src/serviceFeatures/redFlag.ts +++ b/src/serviceFeatures/redFlag.ts @@ -50,7 +50,7 @@ export async function deleteFlagFile(host: NecessaryServices, log: LogFunction) { +async function askAndActivateRemoteDatabase(host: NecessaryServices<"UI" | "setting", never>, log: LogFunction) { const settings = host.services.setting.currentSettings(); if (settings.remoteConfigurations && Object.keys(settings.remoteConfigurations).length > 1) { const message = @@ -216,7 +216,7 @@ export function createFetchAllFlagHandler( * @returns updated configuration if applied, otherwise null. */ export async function adjustSettingToRemote( - host: NecessaryServices<"tweakValue" | "UI" | "setting", any>, + host: NecessaryServices<"tweakValue" | "UI" | "setting", never>, log: LogFunction, config: ObsidianLiveSyncSettings ) { @@ -243,7 +243,7 @@ export async function adjustSettingToRemote( const necessary = extractObject(TweakValuesShouldMatchedTemplate, remoteTweaks); // Check if any necessary tweak value is different from current config. const differentItems = Object.entries(necessary).filter(([key, value]) => { - return (config as any)[key] !== value; + return config[key as keyof ObsidianLiveSyncSettings] !== value; }); if (differentItems.length === 0) { log("Remote configuration matches local configuration. No changes applied.", LOG_LEVEL_NOTICE); @@ -261,7 +261,7 @@ export async function adjustSettingToRemote( config = { ...config, ...Object.fromEntries(differentItems), - } satisfies ObsidianLiveSyncSettings; + }; await host.services.setting.applyExternalSettings(config, true); log("Remote configuration applied.", LOG_LEVEL_NOTICE); canProceed = true; @@ -277,7 +277,7 @@ export async function adjustSettingToRemote( * @param config current configuration to retrieve remote preferred config */ export async function adjustSettingToRemoteIfNeeded( - host: NecessaryServices<"tweakValue" | "UI" | "setting", any>, + host: NecessaryServices<"tweakValue" | "UI" | "setting", never>, log: LogFunction, extra: { preventFetchingConfig: boolean }, config: ObsidianLiveSyncSettings @@ -309,7 +309,7 @@ export async function adjustSettingToRemoteIfNeeded( * @returns result of the process, or false if error occurs. */ export async function processVaultInitialisation( - host: NecessaryServices<"setting", any>, + host: NecessaryServices<"setting", never>, log: LogFunction, proc: () => Promise, keepSuspending = false @@ -341,7 +341,7 @@ export async function processVaultInitialisation( } export async function verifyAndUnlockSuspension( - host: NecessaryServices<"setting" | "appLifecycle" | "UI", any>, + host: NecessaryServices<"setting" | "appLifecycle" | "UI", never>, log: LogFunction ) { if (!host.services.setting.currentSettings().suspendFileWatching) { diff --git a/src/serviceModules/FileSystemAdapters/ObsidianTypeGuardAdapter.ts b/src/serviceModules/FileSystemAdapters/ObsidianTypeGuardAdapter.ts index 455affb..e7b6fb4 100644 --- a/src/serviceModules/FileSystemAdapters/ObsidianTypeGuardAdapter.ts +++ b/src/serviceModules/FileSystemAdapters/ObsidianTypeGuardAdapter.ts @@ -6,11 +6,11 @@ import { TFile, TFolder } from "obsidian"; */ export class ObsidianTypeGuardAdapter implements ITypeGuardAdapter { - isFile(file: any): file is TFile { + isFile(file: unknown): file is TFile { return file instanceof TFile; } - isFolder(item: any): item is TFolder { + isFolder(item: unknown): item is TFolder { return item instanceof TFolder; } } diff --git a/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.ts b/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.ts index bb89774..cc360d5 100644 --- a/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.ts +++ b/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.ts @@ -55,6 +55,7 @@ export class ObsidianVaultAdapter implements IVaultAdapter { return await this.app.vault.trash(file, force); } + // eslint-disable-next-line @typescript-eslint/no-explicit-any trigger(name: string, ...data: any[]): any { return this.app.vault.trigger(name, ...data); }