From fb93511ae75a29343cbae52f98605ee325b270e8 Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Thu, 18 Jun 2026 11:09:07 +0100 Subject: [PATCH] Improve typings Remove `DEV` blocks --- eslint.config.common.mjs | 2 +- eslint.config.mjs | 3 +- src/LiveSyncBaseCore.ts | 3 +- src/apps/cli/main.ts | 14 ++-- .../managers/CLIStorageEventManagerAdapter.ts | 2 +- src/apps/cli/node-compat.ts | 8 +- .../cli/testdeno/helpers/backgroundCli.ts | 4 +- src/apps/cli/testdeno/test-setup-put-cat.ts | 2 +- src/apps/cli/vite.config.ts | 7 +- src/apps/webapp/tsconfig.json | 2 +- src/apps/webapp/vaultSelector.ts | 2 +- src/apps/webapp/vite.config.ts | 8 +- src/common/KeyValueDB.ts | 4 +- src/common/KeyValueDBv2.ts | 6 +- src/common/PeriodicProcessor.ts | 4 +- src/common/reportTool.ts | 10 +-- src/common/utils.ts | 26 +++---- src/deps.ts | 3 + src/features/ConfigSync/CmdConfigSync.ts | 2 +- .../HiddenFileSync/CmdHiddenFileSync.ts | 2 +- src/features/LiveSyncCommands.ts | 16 ++-- .../CmdLocalDatabaseMainte.ts | 11 +-- src/lib | 2 +- src/main.ts | 4 +- .../ObsidianStorageEventManagerAdapter.ts | 4 +- src/modules/AbstractModule.ts | 30 +++---- src/modules/AbstractObsidianModule.ts | 7 -- src/modules/ModuleTypes.ts | 55 ------------- src/modules/core/ModuleReplicator.ts | 4 +- src/modules/core/ReplicateResultProcessor.ts | 7 +- .../ModuleResolveMismatchedTweaks.ts | 2 +- src/modules/coreObsidian/UILib/dialogs.ts | 7 +- .../APILib/ObsHttpHandler.ts | 2 +- .../essentialObsidian/ModuleObsidianEvents.ts | 3 +- src/modules/extras/ModuleDev.ts | 58 +------------- src/modules/extras/devUtil/testUtils.ts | 50 ------------ .../DocumentHistory/DocumentHistoryModal.ts | 8 +- src/modules/features/ModuleGlobalHistory.ts | 3 +- src/modules/features/ModuleLog.ts | 4 +- .../SettingDialogue/LiveSyncSetting.ts | 31 +------- .../ObsidianLiveSyncSettingTab.ts | 78 +++++++------------ .../features/SettingDialogue/PaneChangeLog.ts | 3 +- .../features/SettingDialogue/PaneHatch.ts | 5 +- .../SettingDialogue/PaneRemoteConfig.ts | 8 +- .../features/SettingDialogue/PaneSetup.ts | 8 +- .../features/SettingDialogue/SveltePanel.ts | 4 +- .../features/SettingDialogue/settingUtils.ts | 5 +- .../SettingDialogue/utilFixCouchDBSetting.ts | 5 +- .../dialogs/PanelCouchDBCheck.svelte | 6 +- .../SetupWizard/dialogs/utilCheckCouchDB.ts | 40 ++++++---- src/modules/services/ObsidianAPIService.ts | 11 +-- src/serviceFeatures/redFlag.ts | 14 ++-- .../ObsidianTypeGuardAdapter.ts | 4 +- .../ObsidianVaultAdapter.ts | 4 +- utilsdeno/detect-any.ts | 6 +- utilsdeno/refactor-assertions.ts | 3 +- utilsdeno/refactor-cli-node-imports.ts | 6 +- utilsdeno/refactor-unused.ts | 21 ++--- vite.config.ts | 13 +++- 59 files changed, 245 insertions(+), 421 deletions(-) delete mode 100644 src/modules/ModuleTypes.ts delete mode 100644 src/modules/extras/devUtil/testUtils.ts diff --git a/eslint.config.common.mjs b/eslint.config.common.mjs index d8c6044..e9e3602 100644 --- a/eslint.config.common.mjs +++ b/eslint.config.common.mjs @@ -97,7 +97,7 @@ export const obsidianRules = { // -- Plugin specific overrides "obsidianmd/rule-custom-message": "off", "obsidianmd/ui/sentence-case": "off", - "obsidianmd/no-plugin-as-component": "off", + "obsidianmd/no-plugin-as-component": "warn", // -- Temporary overrides for migration "obsidianmd/no-static-styles-assignment": "off", diff --git a/eslint.config.mjs b/eslint.config.mjs index 624bd2a..69384d2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -86,8 +86,6 @@ export default defineConfig([ parserOptions: { parser: tsParser, extraFileExtensions: [".svelte"], - project: "./tsconfig.json", - rootDir: "./", }, }, rules: { @@ -96,6 +94,7 @@ export default defineConfig([ // it may improve in the future with some options as like ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],] "no-unused-vars": "off", ...obsidianRules, + "obsidianmd/no-plugin-as-component": "off", ...ImportAliasRules("."), }, }, diff --git a/src/LiveSyncBaseCore.ts b/src/LiveSyncBaseCore.ts index 9a49451..301b143 100644 --- a/src/LiveSyncBaseCore.ts +++ b/src/LiveSyncBaseCore.ts @@ -29,6 +29,7 @@ import { ModuleLiveSyncMain } from "./modules/main/ModuleLiveSyncMain"; import type { ServiceModules } from "./lib/src/interfaces/ServiceModule"; import { ModuleBasicMenu } from "./modules/essential/ModuleBasicMenu"; import { usePrepareDatabaseForUse } from "./lib/src/serviceFeatures/prepareDatabaseForUse"; +import type { Constructor } from "@lib/common/utils.type"; export class LiveSyncBaseCore< T extends ServiceContext = ServiceContext, @@ -120,7 +121,7 @@ export class LiveSyncBaseCore< * @param constructor * @returns */ - getModule(constructor: new (...args: any[]) => T): T { + getModule(constructor: Constructor): T { for (const module of this.modules) { if (module.constructor === constructor) return module as T; } diff --git a/src/apps/cli/main.ts b/src/apps/cli/main.ts index 3fc94e9..d8c682d 100644 --- a/src/apps/cli/main.ts +++ b/src/apps/cli/main.ts @@ -232,8 +232,8 @@ async function createDefaultSettingsFile(options: CLIOptions) { const targetPath = options.settingsPath ? path.resolve(options.settingsPath) : options.commandArgs[0] - ? path.resolve(options.commandArgs[0]) - : path.resolve(process.cwd(), "data.json"); + ? path.resolve(options.commandArgs[0]) + : path.resolve(process.cwd(), "data.json"); if (!options.force) { try { @@ -323,8 +323,8 @@ export async function main() { options.command === "mirror" && options.commandArgs[0] ? path.resolve(options.commandArgs[0]) : options.vaultPath - ? path.resolve(options.vaultPath) - : databasePath!; + ? path.resolve(options.vaultPath) + : databasePath!; // Check if vault directory exists try { @@ -458,8 +458,8 @@ export async function main() { if (rules.shouldIgnore(targetPath)) { return false; } - // undefined = pass through to next handler in chain - return undefined; + // At least this handler think it is a target file, but other handlers may still veto it. + return true; }, 0); } } @@ -557,7 +557,7 @@ export async function main() { if (options.command === "daemon" && result) { // Keep the process running - await new Promise(() => { }); + await new Promise(() => {}); } else { await core.services.control.onUnload(); } diff --git a/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts b/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts index 0e82065..d10a508 100644 --- a/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts +++ b/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts @@ -99,7 +99,7 @@ class CLIWatchAdapter implements IStorageEventWatchAdapter { private basePath: string, private ignoreRules?: IgnoreRules, private watchEnabled: boolean = false - ) { } + ) {} private _toNodeFile(filePath: string, stats: Stats | undefined): NodeFile { return { diff --git a/src/apps/cli/node-compat.ts b/src/apps/cli/node-compat.ts index 10e2c9e..ff6aeac 100644 --- a/src/apps/cli/node-compat.ts +++ b/src/apps/cli/node-compat.ts @@ -4,10 +4,4 @@ import * as nodeFsPromises from "node:fs/promises"; import * as nodePath from "node:path"; import * as nodeReadlinePromises from "node:readline/promises"; import type { Stats } from "node:fs"; -export { - nodeFs as fs, - nodeFsPromises as fsPromises, - nodePath as path, - nodeReadlinePromises as readline, - type Stats, -}; +export { nodeFs as fs, nodeFsPromises as fsPromises, nodePath as path, nodeReadlinePromises as readline, type Stats }; diff --git a/src/apps/cli/testdeno/helpers/backgroundCli.ts b/src/apps/cli/testdeno/helpers/backgroundCli.ts index f2cbbb4..ef81fea 100644 --- a/src/apps/cli/testdeno/helpers/backgroundCli.ts +++ b/src/apps/cli/testdeno/helpers/backgroundCli.ts @@ -77,9 +77,7 @@ export class BackgroundCliProcess { if (this.combined.includes(needle)) return; const status = await Promise.race([ this.child.status.then((s) => ({ type: "status" as const, status: s })), - new Promise<{ type: "tick" }>((resolve) => - setTimeout(() => resolve({ type: "tick" }), 100) - ), + new Promise<{ type: "tick" }>((resolve) => setTimeout(() => resolve({ type: "tick" }), 100)), ]); if (status.type === "status") { throw new Error( diff --git a/src/apps/cli/testdeno/test-setup-put-cat.ts b/src/apps/cli/testdeno/test-setup-put-cat.ts index e1d99c9..4494a1f 100644 --- a/src/apps/cli/testdeno/test-setup-put-cat.ts +++ b/src/apps/cli/testdeno/test-setup-put-cat.ts @@ -132,7 +132,7 @@ Deno.test("CLI file operations: push / cat / ls / info / rm / resolve / cat-rev assertEquals(data.path, REMOTE_PATH, "info .path mismatch"); assertEquals(data.filename, REMOTE_PATH.split("/").at(-1), "info .filename mismatch"); assert(typeof data.size === "number" && data.size >= 0, `info .size invalid: ${data.size}`); - assert(typeof data.chunks === "number" && (data.chunks) >= 1, `info .chunks invalid: ${data.chunks}`); + assert(typeof data.chunks === "number" && data.chunks >= 1, `info .chunks invalid: ${data.chunks}`); assertEquals(data.conflicts, "N/A", "info .conflicts should be N/A"); console.log("[PASS] info output format matched"); }); diff --git a/src/apps/cli/vite.config.ts b/src/apps/cli/vite.config.ts index 01992e1..e3e4398 100644 --- a/src/apps/cli/vite.config.ts +++ b/src/apps/cli/vite.config.ts @@ -2,9 +2,12 @@ import { defineConfig } from "vite"; import { svelte } from "@sveltejs/vite-plugin-svelte"; import path from "node:path"; import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); const resolve = (...args: string[]) => path.resolve(...args).replace(/\\/g, "/"); -const packageJson = JSON.parse(readFileSync("../../../package.json", "utf-8")); -const manifestJson = JSON.parse(readFileSync("../../../manifest.json", "utf-8")); +const repoRoot = path.resolve(__dirname, "../../.."); +const packageJson = JSON.parse(readFileSync(path.resolve(repoRoot, "package.json"), "utf-8")); +const manifestJson = JSON.parse(readFileSync(path.resolve(repoRoot, "manifest.json"), "utf-8")); // https://vite.dev/config/ const defaultExternal = [ "obsidian", diff --git a/src/apps/webapp/tsconfig.json b/src/apps/webapp/tsconfig.json index c838f6e..58ad90c 100644 --- a/src/apps/webapp/tsconfig.json +++ b/src/apps/webapp/tsconfig.json @@ -27,6 +27,6 @@ "@lib/*": ["../../lib/src/*"] } }, - "include": ["*.ts", "**/*.ts", "**/*.tsx"], + "include": ["*.ts", "**/*.ts", "**/*.tsx", "**/*.svelte"], "exclude": ["node_modules", "dist"] } diff --git a/src/apps/webapp/vaultSelector.ts b/src/apps/webapp/vaultSelector.ts index 37b7573..104e29c 100644 --- a/src/apps/webapp/vaultSelector.ts +++ b/src/apps/webapp/vaultSelector.ts @@ -91,7 +91,7 @@ export class VaultHistoryStore { async getVaultHistory(): Promise { return this.withStore("readonly", async (store) => { - const keys = (await this.requestAsPromise(store.getAllKeys())); + const keys = await this.requestAsPromise(store.getAllKeys()); const values = (await this.requestAsPromise(store.getAll())) as unknown[]; const items: VaultHistoryItem[] = []; for (let i = 0; i < keys.length; i++) { diff --git a/src/apps/webapp/vite.config.ts b/src/apps/webapp/vite.config.ts index f58d3db..a82a148 100644 --- a/src/apps/webapp/vite.config.ts +++ b/src/apps/webapp/vite.config.ts @@ -3,10 +3,12 @@ import { svelte } from "@sveltejs/vite-plugin-svelte"; import istanbul from "vite-plugin-istanbul"; import path from "node:path"; import { readFileSync } from "node:fs"; -const packageJson = JSON.parse(readFileSync("../../../package.json", "utf-8")); -const manifestJson = JSON.parse(readFileSync("../../../manifest.json", "utf-8")); -const enableCoverage = process.env.PW_COVERAGE === "1"; +import { fileURLToPath } from "node:url"; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); const repoRoot = path.resolve(__dirname, "../../.."); +const packageJson = JSON.parse(readFileSync(path.resolve(repoRoot, "package.json"), "utf-8")); +const manifestJson = JSON.parse(readFileSync(path.resolve(repoRoot, "manifest.json"), "utf-8")); +const enableCoverage = process.env.PW_COVERAGE === "1"; // https://vite.dev/config/ export default defineConfig({ plugins: [ diff --git a/src/common/KeyValueDB.ts b/src/common/KeyValueDB.ts index 64e8398..a3a1d93 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/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 ef9d305..6a0a0cf 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")); } @@ -117,7 +117,7 @@ export class IDBKeyValueDatabase implements KeyValueDatabase { } async get(key: IDBValidKey): Promise { const db = await this.DB; - return await db.get(this.storeKey, key); + return (await db.get(this.storeKey, key)) as U; } async set(key: IDBValidKey, value: U): Promise { const db = await this.DB; 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 2899528..8ec2405 100644 --- a/src/common/reportTool.ts +++ b/src/common/reportTool.ts @@ -9,16 +9,16 @@ 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 +27,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 +42,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 2333b1f..cafa3f3 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: { [key: string]: unknown } = {}; 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; } >(); @@ -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/deps.ts b/src/deps.ts index cf8ed5b..bc1414e 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -31,6 +31,7 @@ export { TextComponent, ToggleComponent, DropdownComponent, + Component, } from "obsidian"; export type { DataWriteOptions, @@ -41,6 +42,8 @@ export type { ListedFiles, ValueComponent, Stat, + Command, + ViewCreator, } from "obsidian"; import { normalizePath as normalizePath_ } from "obsidian"; const normalizePath = normalizePath_ as (from: T) => T; diff --git a/src/features/ConfigSync/CmdConfigSync.ts b/src/features/ConfigSync/CmdConfigSync.ts index a07e1f4..8fbd22e 100644 --- a/src/features/ConfigSync/CmdConfigSync.ts +++ b/src/features/ConfigSync/CmdConfigSync.ts @@ -1101,7 +1101,7 @@ export class ConfigSync extends LiveSyncCommands { 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[]; + const manifests = Object.values(this.app.plugins.manifests) as unknown as PluginManifest[]; //@ts-ignore const enabledPlugins = this.app.plugins.enabledPlugins as Set; const pluginManifest = manifests.find( diff --git a/src/features/HiddenFileSync/CmdHiddenFileSync.ts b/src/features/HiddenFileSync/CmdHiddenFileSync.ts index 20ef7c3..6a36a67 100644 --- a/src/features/HiddenFileSync/CmdHiddenFileSync.ts +++ b/src/features/HiddenFileSync/CmdHiddenFileSync.ts @@ -1225,7 +1225,7 @@ Offline Changed files: ${files.length}`; this.queuedNotificationFiles.clear(); try { //@ts-ignore - const manifests = Object.values(this.app.plugins.manifests) as any as PluginManifest[]; + const manifests = Object.values(this.app.plugins.manifests) as unknown as PluginManifest[]; //@ts-ignore const enabledPlugins = this.app.plugins.enabledPlugins as Set; const enabledPluginManifests = manifests.filter((e) => enabledPlugins.has(e.id)); diff --git a/src/features/LiveSyncCommands.ts b/src/features/LiveSyncCommands.ts index 6eb163b..db7c117 100644 --- a/src/features/LiveSyncCommands.ts +++ b/src/features/LiveSyncCommands.ts @@ -11,7 +11,7 @@ import { import type ObsidianLiveSyncPlugin from "@/main.ts"; import { MARK_DONE } from "@/modules/features/ModuleLog.ts"; import type { LiveSyncCore } from "@/main.ts"; -import { __$checkInstanceBinding } from "@lib/dev/checks.ts"; +// import { __$checkInstanceBinding } from "@lib/dev/checks.ts"; import { createInstanceLogFunction } from "@lib/services/lib/logUtils.ts"; let noticeIndex = 0; @@ -50,7 +50,7 @@ export abstract class LiveSyncCommands { this.core = core; this.onBindFunction(this.core, this.core.services); this._log = createInstanceLogFunction(this.constructor.name, this.services.API); - __$checkInstanceBinding(this); + // __$checkInstanceBinding(this); } abstract onunload(): void; abstract onload(): void | Promise; @@ -67,24 +67,24 @@ 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) => { + log: (msg: string) => { this._log(prefix + msg, level, key); }, - once: (msg: any) => { + once: (msg: string) => { this._log(prefix + msg, level); }, done: (msg: string = "Done") => { @@ -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 42e9096..631856b 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/replication/couchdb/LiveSyncReplicator"; import { delay } from "@lib/common/utils"; +import { isNotFoundError } from "@/lib/src/common/utils.doc"; // import { _requestToCouchDB } from "@/common/utils"; const DB_KEY_SEQ = "gc-seq"; const DB_KEY_CHUNK_SET = "chunk-set"; @@ -394,7 +395,7 @@ Note: **Make sure to synchronise all devices before deletion.** } } } catch (ex) { - if ((ex as any)?.status == 404) { + if (isNotFoundError(ex)) { this._log(`No revisions found for ${doc._id}`, LOG_LEVEL_VERBOSE); } else { this._log(`Error finding revisions for ${doc._id}`); @@ -474,14 +475,14 @@ Are you ready to delete unused chunks?`; include_docs: true, }); for (const chunk of deleteChunks.rows) { - if ((chunk as any)?.value?.deleted) { + if ((chunk as { value?: { deleted?: boolean } })?.value?.deleted) { chunkSet.delete(chunk.key as DocumentID); } } const deleteDocs = deleteChunks.rows .filter((e) => "doc" in e) .map((e) => ({ - ...(e as any).doc!, + ...(e as { doc?: EntryLeaf }).doc!, _deleted: true, })); @@ -490,7 +491,7 @@ Are you ready to delete unused chunks?`; let successCount = 0; let errored = 0; for (const batch of deleteChunkBatch) { - const results = await this.database.bulkDocs(batch as EntryLeaf[]); + const results = await this.database.bulkDocs(batch); for (const result of results) { if ("ok" in result) { chunkSet.delete(result.id as DocumentID); @@ -698,7 +699,7 @@ Success: ${successCount}, Errored: ${errored}`; sharedChunkCount: 0, uniqueChunkSize: orphanChunkSize, sharedChunkSize: 0, - } as any); + } as const); const csvSrc = result.map((e) => { return [ diff --git a/src/lib b/src/lib index c926417..0278343 160000 --- a/src/lib +++ b/src/lib @@ -1 +1 @@ -Subproject commit c926417f82a4bf90e2e6fbc1ad3071a49077c52e +Subproject commit 0278343fc676ed3b94302eac7249ab0ceeae01ee diff --git a/src/main.ts b/src/main.ts index 3de86ce..d02a208 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,7 +4,7 @@ setGetLanguage(getLanguage); import { LiveSyncCommands } from "./features/LiveSyncCommands.ts"; import { HiddenFileSync } from "./features/HiddenFileSync/CmdHiddenFileSync.ts"; import { ConfigSync } from "./features/ConfigSync/CmdConfigSync.ts"; -import { ModuleDev } from "./modules/extras/ModuleDev.ts"; +// import { ModuleDev } from "./modules/extras/ModuleDev.ts"; import { ModuleInteractiveConflictResolver } from "./modules/features/ModuleInteractiveConflictResolver.ts"; import { ModuleLog } from "./modules/features/ModuleLog.ts"; @@ -153,7 +153,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { new ModuleObsidianDocumentHistory(this, core), new ModuleInteractiveConflictResolver(this, core), new ModuleObsidianGlobalHistory(this, core), - new ModuleDev(this, core), + // new ModuleDev(this, core), new SetupManager(core), // this should be moved to core? new ModuleMigration(core), ]; 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) { - 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, true, ""); - } catch (ex: any) { - this.addTestResult(key, false, "Failed by Exception", ex.toString()); - return this.testFail(`${key} failed: ${ex}`); - } - return this.testDone(); - } + // 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, true, ""); + // } catch (ex: any) { + // this.addTestResult(key, false, "Failed by Exception", ex.toString()); + // return this.testFail(`${key} failed: ${ex}`); + // } + // return this.testDone(); + // } isMainReady() { return this.services.appLifecycle.isReady(); diff --git a/src/modules/AbstractObsidianModule.ts b/src/modules/AbstractObsidianModule.ts index 44a952c..0dcfb13 100644 --- a/src/modules/AbstractObsidianModule.ts +++ b/src/modules/AbstractObsidianModule.ts @@ -1,13 +1,6 @@ -import { type Prettify } from "@lib/common/types"; import type { LiveSyncCore } from "@/main"; import type ObsidianLiveSyncPlugin from "@/main"; import { AbstractModule } from "./AbstractModule.ts"; -import type { ChainableExecuteFunction, OverridableFunctionsKeys } from "./ModuleTypes"; - -export type IObsidianModuleBase = OverridableFunctionsKeys; -export type IObsidianModule = Prettify>; -export type ModuleKeys = keyof IObsidianModule; -export type ChainableModuleProps = ChainableExecuteFunction; export abstract class AbstractObsidianModule extends AbstractModule { get app() { diff --git a/src/modules/ModuleTypes.ts b/src/modules/ModuleTypes.ts deleted file mode 100644 index 869acea..0000000 --- a/src/modules/ModuleTypes.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { Prettify } from "@lib/common/types"; -import type { LiveSyncCore } from "@/main"; - -export type OverridableFunctionsKeys = { - [K in keyof T as K extends `$${string}` ? K : never]: T[K]; -}; - -export type ChainableExecuteFunction = { - [K in keyof T as K extends `$${string}` - ? T[K] extends (...args: any) => ChainableFunctionResult - ? K - : never - : never]: T[K]; -}; - -export type ICoreModuleBase = OverridableFunctionsKeys; -export type ICoreModule = Prettify>; -export type CoreModuleKeys = keyof ICoreModule; - -export type ChainableFunctionResult = - | Promise - | Promise - | Promise - | Promise; -export type ChainableFunctionResultOrAll = Promise; - -type AllExecuteFunction = { - [K in keyof T as K extends `$all${string}` - ? 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 - ? K - : never - : never]: T[K]; -}; -type AnyExecuteFunction = { - [K in keyof T as K extends `$any${string}` - ? T[K] extends (...args: any[]) => ChainableFunctionResult - ? K - : never - : never]: T[K]; -}; -type InjectableFunction = { - [K in keyof T as K extends `$$${string}` ? (T[K] extends (...args: any[]) => any ? K : never) : never]: T[K]; -}; -export type AllExecuteProps = AllExecuteFunction; -export type EveryExecuteProps = EveryExecuteFunction; -export type AnyExecuteProps = AnyExecuteFunction; - -export type AllInjectableProps = InjectableFunction; diff --git a/src/modules/core/ModuleReplicator.ts b/src/modules/core/ModuleReplicator.ts index 3479369..806a825 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 013c297..79b1a03 100644 --- a/src/modules/core/ReplicateResultProcessor.ts +++ b/src/modules/core/ReplicateResultProcessor.ts @@ -22,6 +22,7 @@ import { Semaphore } from "octagonal-wheels/concurrency/semaphore_v2"; import { serialized } from "octagonal-wheels/concurrency/lock"; import type { ReactiveSource } from "octagonal-wheels/dataobject/reactive_v2"; import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore"; +import { isNotFoundError } from "@lib/common/utils.doc"; const KV_KEY_REPLICATION_RESULT_PROCESSOR_SNAPSHOT = "replicationResultProcessorSnapshot"; type ReplicateResultProcessorState = { @@ -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) { + if (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 275703a..c05f8dd 100644 --- a/src/modules/coreFeatures/ModuleResolveMismatchedTweaks.ts +++ b/src/modules/coreFeatures/ModuleResolveMismatchedTweaks.ts @@ -18,7 +18,7 @@ import type { InjectableServiceHub } from "@lib/services/InjectableServices.ts"; import type { LiveSyncCore } from "@/main.ts"; import { REMOTE_P2P } from "@lib/common/models/setting.const.ts"; -function valueToString(value: any) { +function valueToString(value: string | number | boolean | object | undefined): string { if (typeof value === "boolean") { return value ? "true" : "false"; } diff --git a/src/modules/coreObsidian/UILib/dialogs.ts b/src/modules/coreObsidian/UILib/dialogs.ts index 93ac895..15d8050 100644 --- a/src/modules/coreObsidian/UILib/dialogs.ts +++ b/src/modules/coreObsidian/UILib/dialogs.ts @@ -1,5 +1,5 @@ import { ButtonComponent } from "@/deps.ts"; -import { App, FuzzySuggestModal, MarkdownRenderer, Modal, Plugin, Setting } from "@/deps.ts"; +import { App, FuzzySuggestModal, MarkdownRenderer, Modal, Plugin, Setting, Component } from "@/deps.ts"; import { EVENT_PLUGIN_UNLOADED, eventHub } from "@/common/events.ts"; import { compatGlobal, type CompatIntervalHandle } from "@lib/common/coreEnvFunctions.ts"; @@ -148,6 +148,7 @@ export class MessageBox extends AutoClosableModal { wideButton: boolean; onSubmit: (result: string | false) => void; + component: Component = new Component(); constructor( plugin: Plugin, @@ -189,6 +190,7 @@ export class MessageBox extends AutoClosableModal { } override onOpen() { + this.component.load(); const { contentEl } = this; this.titleEl.setText(this.title); const div = contentEl.createDiv(); @@ -196,7 +198,7 @@ export class MessageBox extends AutoClosableModal { userSelect: "text", webkitUserSelect: "text", }); - void MarkdownRenderer.render(this.plugin.app, this.contentMd, div, "/", this.plugin); + void MarkdownRenderer.render(this.plugin.app, this.contentMd, div, "/", this.component); const buttonSetting = new Setting(contentEl); const labelWrapper = contentEl.createDiv(); labelWrapper.addClass("sls-dialogue-note-wrapper"); @@ -254,6 +256,7 @@ export class MessageBox extends AutoClosableModal { override onClose() { super.onClose(); + this.component.unload(); const { contentEl } = this; contentEl.empty(); if (this.timer) { diff --git a/src/modules/essentialObsidian/APILib/ObsHttpHandler.ts b/src/modules/essentialObsidian/APILib/ObsHttpHandler.ts index c0dbdcf..e9818b3 100644 --- a/src/modules/essentialObsidian/APILib/ObsHttpHandler.ts +++ b/src/modules/essentialObsidian/APILib/ObsHttpHandler.ts @@ -80,7 +80,7 @@ export class ObsHttpHandler extends FetchHttpHandler { contentType = transformedHeaders["content-type"]; } - let transformedBody: any = body; + let transformedBody = body; if (ArrayBuffer.isView(body)) { transformedBody = new Uint8Array(body.buffer).buffer; } diff --git a/src/modules/essentialObsidian/ModuleObsidianEvents.ts b/src/modules/essentialObsidian/ModuleObsidianEvents.ts index 612ce9e..7c482e4 100644 --- a/src/modules/essentialObsidian/ModuleObsidianEvents.ts +++ b/src/modules/essentialObsidian/ModuleObsidianEvents.ts @@ -36,10 +36,11 @@ export class ModuleObsidianEvents extends AbstractObsidianModule { this.services.appLifecycle.performRestart(); } - initialCallback: any; + initialCallback: (() => void) | undefined = undefined; swapSaveCommand() { this._log("Modifying callback of the save command", LOG_LEVEL_VERBOSE); + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Editor Tweaking const saveCommandDefinition = (this.app as any).commands?.commands?.["editor:save-file"]; const save = saveCommandDefinition?.callback; if (typeof save === "function") { diff --git a/src/modules/extras/ModuleDev.ts b/src/modules/extras/ModuleDev.ts index 16994c4..b79e88f 100644 --- a/src/modules/extras/ModuleDev.ts +++ b/src/modules/extras/ModuleDev.ts @@ -1,13 +1,13 @@ -import { delay, fireAndForget } from "octagonal-wheels/promises"; +import { delay } from "octagonal-wheels/promises"; import { __onMissingTranslation } from "@lib/common/i18n"; import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts"; import { LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger"; -import { eventHub } from "@/common/events"; -import { enableTestFunction } from "./devUtil/testUtils.ts"; +// import { enableTestFunction } from "./devUtil/testUtils.ts"; import { TestPaneView, VIEW_TYPE_TEST } from "./devUtil/TestPaneView.ts"; import { writable } from "svelte/store"; import type { FilePathWithPrefix } from "@lib/common/types.ts"; import type { LiveSyncCore } from "@/main.ts"; +import type { WorkspaceLeaf } from "@/deps.ts"; export class ModuleDev extends AbstractObsidianModule { _everyOnloadStart(): Promise { __onMissingTranslation(() => {}); @@ -37,57 +37,7 @@ export class ModuleDev extends AbstractObsidianModule { private _everyOnloadAfterLoadSettings(): Promise { if (!this.settings.enableDebugTools) return Promise.resolve(true); - this.onMissingTranslation = this.onMissingTranslation.bind(this); - __onMissingTranslation((key) => { - void this.onMissingTranslation(key); - }); - type STUB = { - toc: Set; - stub: { [key: string]: { [key: string]: Map> } }; - }; - eventHub.onEvent("document-stub-created", (detail: STUB) => { - fireAndForget(async () => { - const stub = detail.stub; - const toc = detail.toc; - - const stubDocX = Object.entries(stub) - .map(([key, value]) => { - return [ - `## ${key}`, - Object.entries(value) - .map(([key2, value2]) => { - return [ - `### ${key2}`, - [...value2.entries()].map(([key3, value3]) => { - // return `#### ${key3}` + "\n" + JSON.stringify(value3); - const isObsolete = value3["is_obsolete"] ? " (obsolete)" : ""; - const desc = value3["desc"] ?? ""; - const key = value3["key"] ? "Setting key: " + value3["key"] + "\n" : ""; - return `#### ${key3}${isObsolete}\n${key}${desc}\n`; - }), - ].flat(); - }) - .flat(), - ].flat(); - }) - .flat(); - const stubDocMD = - ` -| Icon | Description | -| :---: | ----------------------------------------------------------------- | -` + - [...toc.values()].map((e) => `${e}`).join("\n") + - "\n\n" + - stubDocX.join("\n"); - await this.core.storageAccess.writeHiddenFileAuto( - this.app.vault.configDir + "/ls-debug/stub-doc.md", - stubDocMD - ); - }); - }); - - enableTestFunction(this.plugin); - this.registerView(VIEW_TYPE_TEST, (leaf) => new TestPaneView(leaf, this.plugin, this)); + this.registerView(VIEW_TYPE_TEST, (leaf: WorkspaceLeaf) => new TestPaneView(leaf, this.plugin, this)); this.addCommand({ id: "view-test", name: "Open Test dialogue", diff --git a/src/modules/extras/devUtil/testUtils.ts b/src/modules/extras/devUtil/testUtils.ts deleted file mode 100644 index 6d07265..0000000 --- a/src/modules/extras/devUtil/testUtils.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { fireAndForget } from "@lib/common/utils.ts"; -import { serialized } from "octagonal-wheels/concurrency/lock"; -import type ObsidianLiveSyncPlugin from "@/main.ts"; - -let plugin: ObsidianLiveSyncPlugin; -export function enableTestFunction(plugin_: ObsidianLiveSyncPlugin) { - plugin = plugin_; -} -export function addDebugFileLog(message: any, stackLog = false) { - fireAndForget( - serialized("debug-log", async () => { - const now = new Date(); - const filename = `debug-log`; - const time = now.toISOString().split("T")[0]; - const outFile = `${filename}${time}.jsonl`; - // 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; - if (message instanceof Error) { - // debugger; - // console.dir(message.stack); - out = { ...out, message }; - } else if (stackLog) { - if (stackLog) { - const stackE = new Error(); - const stack = stackE.stack; - out = { ...out, stack }; - } - } - if (typeof message == "object") { - out = { ...out, ...message }; - } else { - out = { - result: message, - }; - } - // const out = "--" + timestamp + "--\n" + messageContent + " " + (stack || ""); - // const out - try { - await plugin.core.storageAccess.appendHiddenFile( - plugin.core.services.API.getSystemConfigDir() + "/ls-debug/" + outFile, - JSON.stringify(out) + "\n" - ); - } catch { - //NO OP - } - }) - ); -} diff --git a/src/modules/features/DocumentHistory/DocumentHistoryModal.ts b/src/modules/features/DocumentHistory/DocumentHistoryModal.ts index 95760a3..8288c7e 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) || 0); 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) || 0) - 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: Event) => { 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: Event) => { 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/ModuleGlobalHistory.ts b/src/modules/features/ModuleGlobalHistory.ts index 2133ba9..08efb9f 100644 --- a/src/modules/features/ModuleGlobalHistory.ts +++ b/src/modules/features/ModuleGlobalHistory.ts @@ -1,5 +1,6 @@ import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts"; import { VIEW_TYPE_GLOBAL_HISTORY, GlobalHistoryView } from "./GlobalHistory/GlobalHistoryView.ts"; +import type { WorkspaceLeaf } from "@/deps.ts"; export class ModuleObsidianGlobalHistory extends AbstractObsidianModule { _everyOnloadStart(): Promise { @@ -11,7 +12,7 @@ export class ModuleObsidianGlobalHistory extends AbstractObsidianModule { }, }); - this.registerView(VIEW_TYPE_GLOBAL_HISTORY, (leaf) => new GlobalHistoryView(leaf, this.plugin)); + this.registerView(VIEW_TYPE_GLOBAL_HISTORY, (leaf: WorkspaceLeaf) => new GlobalHistoryView(leaf, this.plugin)); return Promise.resolve(true); } diff --git a/src/modules/features/ModuleLog.ts b/src/modules/features/ModuleLog.ts index ecb9e1f..635d1d6 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..d3a113e 100644 --- a/src/modules/features/SettingDialogue/LiveSyncSetting.ts +++ b/src/modules/features/SettingDialogue/LiveSyncSetting.ts @@ -9,7 +9,7 @@ import { } from "@/deps.ts"; import { unique } from "octagonal-wheels/collection"; import { LEVEL_ADVANCED, LEVEL_POWER_USER, statusDisplay, type ConfigurationItem } from "@lib/common/types.ts"; -import { createStub, type ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts"; +import { type ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts"; import { type AllSettingItemKey, getConfig, @@ -19,7 +19,7 @@ import { type AllBooleanItemKey, } from "./settingConstants.ts"; import { $msg } from "@lib/common/i18n.ts"; -import { findAttrFromParent, wrapMemo, type AutoWireOption, type OnUpdateResult } from "./SettingPane.ts"; +import { wrapMemo, type AutoWireOption, type OnUpdateResult } from "./SettingPane.ts"; export class LiveSyncSetting extends Setting { autoWiredComponent?: TextComponent | ToggleComponent | DropdownComponent | ButtonComponent | TextAreaComponent; @@ -35,37 +35,19 @@ 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); } - _createDocStub(key: string, value: string | DocumentFragment) { - DEV: { - const paneName = findAttrFromParent(this.settingEl, "data-pane"); - const panelName = findAttrFromParent(this.settingEl, "data-panel"); - const itemName = - typeof this.nameBuf == "string" ? this.nameBuf : (this.nameBuf.textContent?.toString() ?? ""); - const strValue = typeof value == "string" ? value : (value.textContent?.toString() ?? ""); - - createStub(itemName, key, strValue, panelName, paneName); - } - } - override setDesc(desc: string | DocumentFragment): this { this.descBuf = desc; - DEV: { - this._createDocStub("desc", desc); - } super.setDesc(desc); return this; } override setName(name: string | DocumentFragment): this { this.nameBuf = name; - DEV: { - this._createDocStub("name", name); - } super.setName(name); return this; } @@ -84,11 +66,6 @@ export class LiveSyncSetting extends Setting { if (conf.desc) { this.setDesc(conf.desc); } - DEV: { - this._createDocStub("key", key); - if (conf.obsolete) this._createDocStub("is_obsolete", "true"); - if (conf.level) this._createDocStub("level", conf.level); - } this.holdValue = opt?.holdValue || this.holdValue; this.selfKey = key; @@ -102,7 +79,7 @@ export class LiveSyncSetting extends Setting { } return conf; } - autoWireComponent(component: ValueComponent, conf?: ConfigurationItem, opt?: AutoWireOption) { + autoWireComponent(component: ValueComponent, conf?: ConfigurationItem, opt?: AutoWireOption) { this.placeHolderBuf = conf?.placeHolder || opt?.placeHolder || ""; if (conf?.level == LEVEL_ADVANCED) { this.settingEl.toggleClass("sls-setting-advanced", true); diff --git a/src/modules/features/SettingDialogue/ObsidianLiveSyncSettingTab.ts b/src/modules/features/SettingDialogue/ObsidianLiveSyncSettingTab.ts index db02133..6e9a107 100644 --- a/src/modules/features/SettingDialogue/ObsidianLiveSyncSettingTab.ts +++ b/src/modules/features/SettingDialogue/ObsidianLiveSyncSettingTab.ts @@ -1,4 +1,4 @@ -import { App, PluginSettingTab } from "@/deps.ts"; +import { App, Component, PluginSettingTab } from "@/deps.ts"; import { type ObsidianLiveSyncSettings, type RemoteDBSettings, @@ -40,12 +40,13 @@ import { JournalSyncMinio } from "@lib/replication/journal/objectstore/JournalSy import { paneChangeLog } from "./PaneChangeLog.ts"; import { enableOnly, - findAttrFromParent, - getLevelStr, + // findAttrFromParent, + // getLevelStr, setLevelClass, setStyle, visibleOnly, type OnSavedHandler, + type OnSavedHandlerFunc, type OnUpdateFunc, type OnUpdateResult, type PageFunctions, @@ -65,28 +66,14 @@ import { paneMaintenance } from "./PaneMaintenance.ts"; import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; // For creating a document -const toc = new Set(); -const stubs = {} as { - [key: string]: { [key: string]: Map> }; -}; -export function createStub(name: string, key: string, value: string, panel: string, pane: string) { - DEV: { - if (!(pane in stubs)) { - stubs[pane] = {}; - } - if (!(panel in stubs[pane])) { - stubs[pane][panel] = new Map>(); - } - const old = stubs[pane][panel].get(name) ?? {}; - stubs[pane][panel].set(name, { ...old, [key]: value }); - scheduleTask("update-stub", 100, () => { - eventHub.emitEvent("document-stub-created", { toc: toc, stub: stubs }); - }); - } -} +// const toc = new Set(); export class ObsidianLiveSyncSettingTab extends PluginSettingTab { plugin: ObsidianLiveSyncPlugin; + private _lifetimeComponent: Component = new Component(); + get lifetimeComponent(): Component { + return this._lifetimeComponent; + } get core() { return this.plugin.core; } @@ -181,7 +168,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { // if (runOnSaved) { const handlers = this.onSavedHandlers .filter((e) => appliedKeys.indexOf(e.key) !== -1) - .map((e) => Promise.resolve(e.handler(this.editingSettings[e.key as AllSettingItemKey]))); + .map((e) => Promise.resolve(e.handler(this.editingSettings[e.key]))); await Promise.all(handlers); // } keys.forEach((e) => this.refreshSetting(e)); @@ -287,7 +274,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { // UI Element Wrapper --> settingComponents = [] as Setting[]; controlledElementFunc = [] as UpdateFunction[]; - onSavedHandlers = [] as OnSavedHandler[]; + onSavedHandlers = [] as OnSavedHandler[]; inWizard: boolean = false; @@ -370,8 +357,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { return Promise.resolve(elm); } - addOnSaved(key: T, func: (value: AllSettings[T]) => Promise | void) { - this.onSavedHandlers.push({ key, handler: func }); + addOnSaved(key: T, func: OnSavedHandlerFunc) { + const newHandler = { key, handler: func } as OnSavedHandler; + this.onSavedHandlers.push(newHandler); } resetEditingSettings() { this._editingSettings = undefined; @@ -379,6 +367,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { } override hide() { + super.hide(); + this._lifetimeComponent?.unload(); + this._lifetimeComponent = undefined; this.isShown = false; } isShown: boolean = false; @@ -663,8 +654,10 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { } } - display(): void { + override display(): void { const changeDisplay = this.changeDisplay.bind(this); + // Make sure lifetime component is loaded for markdown rendering in panes. + this._lifetimeComponent.load(); const { containerEl } = this; this.settingComponents.length = 0; this.controlledElementFunc.length = 0; @@ -718,7 +711,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { visibleOnly(() => this.isNeedRebuildLocal() || this.isNeedRebuildRemote()) ); - let paneNo = 0; + // let paneNo = 0; const addPane = ( parentEl: HTMLElement, title: string, @@ -728,20 +721,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { level?: ConfigLevel ) => { const el = this.createEl(parentEl, "div", { text: "" }); - DEV: { - const mdTitle = `${paneNo++}. ${title}${getLevelStr(level ?? "")}`; - el.setAttribute("data-pane", mdTitle); - toc.add( - `| ${icon} | [${mdTitle}](#${mdTitle - .toLowerCase() - .replace(/ /g, "-") - .replace(/[^\w\s-]/g, "")}) | ` - ); - } + setLevelClass(el, level); - // TODO: Refactor to use Obsidian's recommended way to create heading. - // eslint-disable-next-line obsidianmd/settings-tab/no-manual-html-headings - el.createEl("h3", { text: title, cls: "sls-setting-pane-title" }); + new Setting(el).setName(title).setHeading().setClass("sls-setting-pane-title"); if (this.menuEl) { this.menuEl.createEl( "label", @@ -772,7 +754,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { // }); return p; }; - const panelNoMap = {} as { [key: string]: number }; + // const panelNoMap = {} as { [key: string]: number }; const addPanel = ( parentEl: HTMLElement, title: string, @@ -781,15 +763,6 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { level?: ConfigLevel ) => { const el = this.createEl(parentEl, "div", { text: "" }, callback, func); - DEV: { - const paneNo = findAttrFromParent(parentEl, "data-pane"); - if (!(paneNo in panelNoMap)) { - panelNoMap[paneNo] = 0; - } - panelNoMap[paneNo] += 1; - const panelNo = panelNoMap[paneNo]; - el.setAttribute("data-panel", `${panelNo}. ${title}${getLevelStr(level ?? "")}`); - } setLevelClass(el, level); this.createEl(el, "h4", { text: title, cls: "sls-setting-panel-title" }); const p = Promise.resolve(el); @@ -823,6 +796,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { return callback; }; + // Add panes + + // TODO: Refactor to new API style. void addPane(containerEl, $msg("obsidianLiveSyncSettingTab.panelChangeLog"), "πŸ’¬", 100, false).then( bindPane(paneChangeLog) ); diff --git a/src/modules/features/SettingDialogue/PaneChangeLog.ts b/src/modules/features/SettingDialogue/PaneChangeLog.ts index eab16c5..7e66317 100644 --- a/src/modules/features/SettingDialogue/PaneChangeLog.ts +++ b/src/modules/features/SettingDialogue/PaneChangeLog.ts @@ -20,7 +20,6 @@ export function paneChangeLog(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElem undefined, visibleOnly(() => !this.isConfiguredAs("versionUpFlash", "")) ); - this.createEl( cx, "div", @@ -58,6 +57,6 @@ export function paneChangeLog(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElem }); } fireAndForget(() => - MarkdownRenderer.render(this.plugin.app, updateInformation, informationDivEl, "/", this.plugin) + MarkdownRenderer.render(this.plugin.app, updateInformation, informationDivEl, "/", this.lifetimeComponent) ); } diff --git a/src/modules/features/SettingDialogue/PaneHatch.ts b/src/modules/features/SettingDialogue/PaneHatch.ts index 18c878f..a5b267c 100644 --- a/src/modules/features/SettingDialogue/PaneHatch.ts +++ b/src/modules/features/SettingDialogue/PaneHatch.ts @@ -6,6 +6,7 @@ import { type LoadedEntry, type MetaEntry, type FilePath, + type EntryDoc, } from "@lib/common/types.ts"; import { createBlob, getFileRegExp, isDocContentSame, readAsBlob } from "@lib/common/utils.ts"; import { Logger } from "@lib/common/logger.ts"; @@ -441,8 +442,8 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, const newData = entriesToDelete.rows.map((e) => ({ ...e.doc, _deleted: true, - })); - const r = await this.core.localDatabase.bulkDocsRaw(newData as any[]); + })) as EntryDoc[]; + const r = await this.core.localDatabase.bulkDocsRaw(newData); // 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 e6c6461..bdc7734 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/common/types.ts"; -import { Menu } from "@/deps.ts"; +import { Menu, type ButtonComponent } from "@/deps.ts"; import { $msg } from "@lib/common/i18n.ts"; import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts"; import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts"; @@ -37,9 +37,9 @@ import { syncActivatedRemoteSettings } from "./remoteConfigBuffer.ts"; function getSettingsFromEditingSettings(editingSettings: AllSettings): ObsidianLiveSyncSettings { const workObj = { ...editingSettings } as ObsidianLiveSyncSettings; - const keys = Object.keys(OnDialogSettingsDefault); + const keys = Object.keys(OnDialogSettingsDefault) as (keyof ObsidianLiveSyncSettings)[]; for (const k of keys) { - delete (workObj as any)[k]; + delete workObj[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 5737b54..061bbc5 100644 --- a/src/modules/features/SettingDialogue/PaneSetup.ts +++ b/src/modules/features/SettingDialogue/PaneSetup.ts @@ -14,6 +14,7 @@ import { visibleOnly } from "./SettingPane.ts"; import { DEFAULT_SETTINGS } from "@lib/common/types.ts"; import { request } from "@/deps.ts"; import { SetupManager, UserMode } from "@/modules/features/SetupManager.ts"; +import { LiveSyncError } from "@/lib/src/common/LSError.ts"; export function paneSetup( this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement, @@ -145,8 +146,9 @@ export function paneSetup( let remoteTroubleShootMDSrc = ""; try { remoteTroubleShootMDSrc = await request(`${rawRepoURI}${basePath}/${filename}`); - } catch (ex: any) { - remoteTroubleShootMDSrc = `${$msg("obsidianLiveSyncSettingTab.logErrorOccurred")}\n${ex.toString()}`; + } catch (ex) { + const err = LiveSyncError.fromError(ex); + remoteTroubleShootMDSrc = `${$msg("obsidianLiveSyncSettingTab.logErrorOccurred")}\n${err.toString()}`; } const remoteTroubleShootMD = remoteTroubleShootMDSrc.replace( /\((.*?(.png)|(.jpg))\)/g, @@ -158,7 +160,7 @@ export function paneSetup( ` [${$msg("obsidianLiveSyncSettingTab.linkTipsAndTroubleshooting")}](${topPath}) [${$msg("obsidianLiveSyncSettingTab.linkPageTop")}](${filename})\n\n${remoteTroubleShootMD}`, troubleShootEl, `${rawRepoURI}`, - this.plugin + this.lifetimeComponent ); // Menu troubleShootEl.querySelector(".sls-troubleshoot-anchor")?.parentElement?.setCssStyles({ 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 ab03844..f15b67d 100644 --- a/src/modules/features/SettingDialogue/settingUtils.ts +++ b/src/modules/features/SettingDialogue/settingUtils.ts @@ -8,6 +8,7 @@ import { } from "@lib/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"; /** * Generates a summary of P2P configuration settings @@ -90,10 +91,10 @@ export function getSummaryFromPartialSettings(setting: Partial | ResultErrorMessage { return "result" in result && result.result === "error"; } - function isFixableError(result: ConfigCheckResult): result is ResultError { + function isFixableError(result: ConfigCheckResult): result is ResultError { return isErrorResult(result) && "fix" in result && typeof result.fix === "function"; } function isSuccessResult(result: ConfigCheckResult): result is { message: string; result: "ok"; value?: any } { return "result" in result && result.result === "ok"; } let processing = $state(false); - async function fixIssue(issue: ResultError) { + async function fixIssue(issue: ResultError) { try { processing = true; await issue.fix(); diff --git a/src/modules/features/SetupWizard/dialogs/utilCheckCouchDB.ts b/src/modules/features/SetupWizard/dialogs/utilCheckCouchDB.ts index 76e725f..590a4a5 100644 --- a/src/modules/features/SetupWizard/dialogs/utilCheckCouchDB.ts +++ b/src/modules/features/SetupWizard/dialogs/utilCheckCouchDB.ts @@ -6,12 +6,17 @@ import { parseHeaderValues } from "@lib/common/utils"; import { isCloudantURI } from "@lib/pouchdb/utils_couchdb"; import { generateCredentialObject } from "@lib/replication/httplib"; import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; +import { isUnauthorizedError } from "@lib/common/utils.doc"; export type ResultMessage = { message: string; classes: string[] }; export type ResultErrorMessage = { message: string; result: "error"; classes: string[] }; -export type ResultOk = { message: string; result: "ok"; value?: any }; -export type ResultError = { message: string; result: "error"; value: any; fixMessage: string; fix(): Promise }; -export type ConfigCheckResult = ResultOk | ResultError | ResultMessage | ResultErrorMessage; +export type ResultOk = { message: string; result: "ok"; value?: T }; +export type ResultError = { message: string; result: "error"; value: T; 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. * @param baseVersion a.b.c format @@ -37,7 +42,11 @@ 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 +): Promise { const customHeaders = parseHeaderValues(setting.couchDB_CustomHeaders); const credential = generateCredentialObject(setting); const res = await requestToCouchDBWithCredentials( @@ -62,24 +71,29 @@ async function updateRemoteSetting(setting: ObsidianLiveSyncSettings, key: strin * @returns Array of ConfigCheckResult */ export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) => { - const result = [] as ConfigCheckResult[]; + const result = [] as ConfigCheckResult[]; const addMessage = (msg: string, classes: string[] = []) => { result.push({ message: msg, classes }); }; - const addSuccess = (msg: string, value?: any) => { + const addSuccess = (msg: string, value?: T) => { 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?: T) => { 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) => { - _addError(message, fixMessage, async () => { - await updateRemoteSetting(editingSettings, key, expected); - }); + const addError = (message: string, fixMessage: string, key: string, expected: string) => { + _addError( + message, + fixMessage, + async () => { + await updateRemoteSetting(editingSettings, key, expected); + }, + expected + ); }; addMessage($msg("obsidianLiveSyncSettingTab.logCheckingDbConfig")); @@ -281,8 +295,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 (isUnauthorizedError(ex)) { 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 ce00f43..daa0a89 100644 --- a/src/modules/services/ObsidianAPIService.ts +++ b/src/modules/services/ObsidianAPIService.ts @@ -1,6 +1,6 @@ import { InjectableAPIService } from "@lib/services/implements/injectable/InjectableAPIService"; import type { ObsidianServiceContext } from "@lib/services/implements/obsidian/ObsidianServiceContext"; -import { Platform, type Command, type ViewCreator } from "obsidian"; +import { Platform, type Command, type ViewCreator } from "@/deps.ts"; import { ObsHttpHandler } from "@/modules/essentialObsidian/APILib/ObsHttpHandler"; import { ObsidianConfirm } from "./ObsidianConfirm"; import type { Confirm } from "@lib/interfaces/Confirm"; @@ -122,14 +122,15 @@ export class ObsidianAPIService extends InjectableAPIService(type: string, factory: (leaf: T) => unknown): void { + return this.context.plugin.registerView(type, factory as ViewCreator); } - addRibbonIcon(icon: string, title: string, callback: (evt: MouseEvent) => any): HTMLElement { + + addRibbonIcon(icon: string, title: string, callback: (evt: MouseEvent) => unknown): HTMLElement { return this.context.plugin.addRibbonIcon(icon, title, callback); } - registerProtocolHandler(action: string, handler: (params: Record) => any): void { + registerProtocolHandler(action: string, handler: (params: Record) => unknown): void { return this.context.plugin.registerObsidianProtocolHandler(action, handler); } diff --git a/src/serviceFeatures/redFlag.ts b/src/serviceFeatures/redFlag.ts index bcbdbe7..4fe9d8d 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); @@ -260,7 +260,7 @@ export async function adjustSettingToRemote( config = { ...config, - ...Object.fromEntries(differentItems), + ...(Object.fromEntries(differentItems) as Partial), } satisfies ObsidianLiveSyncSettings; await host.services.setting.applyExternalSettings(config, true); log("Remote configuration applied.", LOG_LEVEL_NOTICE); @@ -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 9de3a43..74e05bd 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 b178798..5ca9053 100644 --- a/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.ts +++ b/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.ts @@ -6,7 +6,7 @@ import type { TFile, App, TFolder } from "obsidian"; /** * Vault adapter implementation for Obsidian */ -export class ObsidianVaultAdapter implements IVaultAdapter { +export class ObsidianVaultAdapter implements IVaultAdapter { constructor(private app: App) {} async read(file: TFile): Promise { @@ -55,7 +55,7 @@ export class ObsidianVaultAdapter implements IVaultAdapter { return await this.app.vault.trash(file, force); } - trigger(name: string, ...data: any[]): any { + trigger(name: string, ...data: unknown[]): void { return this.app.vault.trigger(name, ...data); } } diff --git a/utilsdeno/detect-any.ts b/utilsdeno/detect-any.ts index f56e11a..b51ef37 100644 --- a/utilsdeno/detect-any.ts +++ b/utilsdeno/detect-any.ts @@ -26,11 +26,7 @@ for (const sourceFile of project.getSourceFiles()) { const posixFilePath = toPosixPath(filePath); if (!posixFilePath.startsWith(posixSrc)) continue; - if ( - posixFilePath.includes("/_test/") || - posixFilePath.endsWith(".spec.ts") || - posixFilePath.endsWith(".test.ts") - ) { + if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts")) { continue; } diff --git a/utilsdeno/refactor-assertions.ts b/utilsdeno/refactor-assertions.ts index 24d8dc4..0beb2db 100644 --- a/utilsdeno/refactor-assertions.ts +++ b/utilsdeno/refactor-assertions.ts @@ -37,7 +37,8 @@ for (const sourceFile of project.getSourceFiles()) { const posixFilePath = toPosixPath(filePath); if (!posixFilePath.startsWith(posixSrc)) continue; - if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts")) continue; + if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts")) + continue; // Find AsExpression (expr as Type) and TypeAssertion (expr) const asExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.AsExpression); diff --git a/utilsdeno/refactor-cli-node-imports.ts b/utilsdeno/refactor-cli-node-imports.ts index 1a828ce..36f8853 100644 --- a/utilsdeno/refactor-cli-node-imports.ts +++ b/utilsdeno/refactor-cli-node-imports.ts @@ -69,7 +69,7 @@ for (const sourceFile of project.getSourceFiles()) { for (const impDecl of importDeclarations) { const specifier = impDecl.getModuleSpecifierValue(); - + // Check if it's a Node.js built-in module we want to redirect let exportedName = ""; if (specifier === "fs/promises" || specifier === "node:fs/promises") { @@ -92,11 +92,11 @@ for (const sourceFile of project.getSourceFiles()) { if (targetImports.length > 0) { console.log(`File: ${posixFilePath.slice(posixProjectRoot.length + 1)}`); - + for (const { impDecl, exportedName, localName } of targetImports) { const { line } = sourceFile.getLineAndColumnAtPos(impDecl.getStart()); console.log(` Line ${line}: Redirecting "${impDecl.getText()}"`); - + if (exportedName === localName) { namedImportsToAdd.push(exportedName); } else { diff --git a/utilsdeno/refactor-unused.ts b/utilsdeno/refactor-unused.ts index d805c32..6be52a6 100644 --- a/utilsdeno/refactor-unused.ts +++ b/utilsdeno/refactor-unused.ts @@ -38,7 +38,8 @@ for (const sourceFile of project.getSourceFiles()) { const posixFilePath = toPosixPath(filePath); if (!posixFilePath.startsWith(posixSrc)) continue; - if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts")) continue; + if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts")) + continue; let fileModified = false; @@ -51,10 +52,11 @@ for (const sourceFile of project.getSourceFiles()) { if (varDec) { const varName = varDec.getName(); // Count references within the catch clause itself - const count = catchClause.getDescendantsOfKind(SyntaxKind.Identifier) - .filter((id) => id.getText() === varName) - .length; - if (count === 1) { // Only the declaration itself + const count = catchClause + .getDescendantsOfKind(SyntaxKind.Identifier) + .filter((id) => id.getText() === varName).length; + if (count === 1) { + // Only the declaration itself catchVarsToRemove.push(varDec); } } @@ -86,10 +88,11 @@ for (const sourceFile of project.getSourceFiles()) { for (const namedImport of namedImports) { const importName = namedImport.getAliasNode()?.getText() ?? namedImport.getName(); // Count references in the entire file - const count = sourceFile.getDescendantsOfKind(SyntaxKind.Identifier) - .filter((id) => id.getText() === importName) - .length; - if (count === 1) { // Only the import specifier itself + const count = sourceFile + .getDescendantsOfKind(SyntaxKind.Identifier) + .filter((id) => id.getText() === importName).length; + if (count === 1) { + // Only the import specifier itself importsToRemove.push({ namedImport, impDecl }); } } diff --git a/vite.config.ts b/vite.config.ts index 0f2c221..a7c47ae 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -9,10 +9,17 @@ import fs from "node:fs"; import { platform } from "node:process"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); +function readJson(filePath: string) { + if (!fs.existsSync(filePath)) { + return {}; + } + return JSON.parse(fs.readFileSync(filePath, "utf-8")); +} -const manifestJson = JSON.parse(fs.readFileSync("./manifest.json") + ""); -const packageJson = JSON.parse(fs.readFileSync("./package.json") + ""); -const updateInfo = JSON.stringify(fs.readFileSync("./updates.md") + ""); +const manifestJson = readJson(path.resolve(__dirname, "manifest.json")); +const packageJson = readJson(path.resolve(__dirname, "package.json")); +const updatesPath = path.resolve(__dirname, "updates.md"); +const updateInfo = JSON.stringify(fs.existsSync(updatesPath) ? fs.readFileSync(updatesPath, "utf-8") : ""); // const moduleAliasPlugin = { // name: "module-alias",