diff --git a/package.json b/package.json index 37609a5..b921e0d 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "lint": "eslint --cache --concurrency auto src", "svelte-check": "svelte-check --tsconfig ./tsconfig.json", "tsc-check": "tsc --noEmit", + "pretty:importpath":"cd utilsdeno && deno run -A ./normalise-imports.ts", "pretty": "npm run prettyNoWrite -- --write --log-level error", "prettyCheck": "npm run prettyNoWrite -- --check", "prettyNoWrite": "prettier --config ./.prettierrc.mjs \"**/*.js\" \"**/*.ts\" \"**/*.json\" ", diff --git a/src/apps/cli/adapters/NodeConversionAdapter.ts b/src/apps/cli/adapters/NodeConversionAdapter.ts index c101608..cdd24a2 100644 --- a/src/apps/cli/adapters/NodeConversionAdapter.ts +++ b/src/apps/cli/adapters/NodeConversionAdapter.ts @@ -1,4 +1,4 @@ -import type { UXFileInfoStub, UXFolderInfo } from "@lib/common/types"; +import type { FilePath, UXFileInfoStub, UXFolderInfo } from "@lib/common/types"; import type { IConversionAdapter } from "@lib/serviceModules/adapters"; import type { NodeFile, NodeFolder } from "./NodeTypes"; import { path } from "@/apps/cli/node-compat"; @@ -22,7 +22,7 @@ export class NodeConversionAdapter implements IConversionAdapter { - isFile(file: any): file is NodeFile { - return file && typeof file === "object" && "path" in file && "stat" in file && !file.isFolder; + isFile(file: unknown): file is NodeFile { + return !!( + file && + typeof file === "object" && + "path" in file && + "stat" in file && + !(file as { isFolder?: boolean }).isFolder + ); } - isFolder(item: any): item is NodeFolder { - return item && typeof item === "object" && "path" in item && item.isFolder === true; + isFolder(item: unknown): item is NodeFolder { + return !!( + item && + typeof item === "object" && + "path" in item && + (item as { isFolder?: boolean }).isFolder === true + ); } } diff --git a/src/apps/cli/adapters/NodeVaultAdapter.ts b/src/apps/cli/adapters/NodeVaultAdapter.ts index 823423d..ecc64ec 100644 --- a/src/apps/cli/adapters/NodeVaultAdapter.ts +++ b/src/apps/cli/adapters/NodeVaultAdapter.ts @@ -1,4 +1,4 @@ -import type { UXDataWriteOptions } from "@lib/common/types"; +import type { FilePath, UXDataWriteOptions } from "@lib/common/types"; import type { IVaultAdapter } from "@lib/serviceModules/adapters"; import type { NodeFile, NodeFolder } from "./NodeTypes"; import { fsPromises as fs, path } from "@/apps/cli/node-compat"; @@ -70,7 +70,7 @@ export class NodeVaultAdapter implements IVaultAdapter { const stat = await fs.stat(fullPath); return { - path: p as any, + path: p as FilePath, stat: { size: stat.size, mtime: Math.floor(stat.mtimeMs), @@ -93,7 +93,7 @@ export class NodeVaultAdapter implements IVaultAdapter { const stat = await fs.stat(fullPath); return { - path: p as any, + path: p as FilePath, stat: { size: stat.size, mtime: Math.floor(stat.mtimeMs), @@ -118,7 +118,7 @@ export class NodeVaultAdapter implements IVaultAdapter { await this.delete(file, force); } - trigger(name: string, ...data: any[]): any { + trigger(name: string, ...data: unknown[]): void { // No-op in CLI version (no event system) return undefined; } diff --git a/src/apps/cli/commands/p2p.ts b/src/apps/cli/commands/p2p.ts index e6542ad..da83244 100644 --- a/src/apps/cli/commands/p2p.ts +++ b/src/apps/cli/commands/p2p.ts @@ -21,7 +21,7 @@ export function parseTimeoutSeconds(value: string, commandName: string): number return timeoutSec; } -function validateP2PSettings(core: LiveSyncBaseCore) { +function validateP2PSettings(core: LiveSyncBaseCore) { const settings = core.services.setting.currentSettings(); if (!settings.P2P_Enabled) { throw new Error("P2P is disabled in settings (P2P_Enabled=false)"); @@ -33,7 +33,7 @@ function validateP2PSettings(core: LiveSyncBaseCore) { settings.P2P_IsHeadless = true; } -async function createReplicator(core: LiveSyncBaseCore): Promise { +async function createReplicator(core: LiveSyncBaseCore): Promise { validateP2PSettings(core); const replicator = await core.services.replicator.getNewReplicator(); if (!replicator) { @@ -52,7 +52,7 @@ function getSortedPeers(replicator: LiveSyncTrysteroReplicator): CLIP2PPeer[] { } export async function collectPeers( - core: LiveSyncBaseCore, + core: LiveSyncBaseCore, timeoutSec: number ): Promise { const replicator = await createReplicator(core); @@ -81,7 +81,7 @@ function resolvePeer(peers: CLIP2PPeer[], peerToken: string): CLIP2PPeer | undef } export async function syncWithPeer( - core: LiveSyncBaseCore, + core: LiveSyncBaseCore, peerToken: string, timeoutSec: number ): Promise { @@ -109,7 +109,7 @@ export async function syncWithPeer( if (pullResult && "error" in pullResult && pullResult.error) { throw pullResult.error; } - const pushResult = (await replicator.requestSynchroniseToPeer(targetPeer.peerId)) as any; + const pushResult = await replicator.requestSynchroniseToPeer(targetPeer.peerId); if (!pushResult || pushResult.ok !== true) { throw pushResult?.error ?? new Error("P2P sync failed while requesting remote sync"); } @@ -120,7 +120,7 @@ export async function syncWithPeer( } } -export async function openP2PHost(core: LiveSyncBaseCore): Promise { +export async function openP2PHost(core: LiveSyncBaseCore): Promise { const replicator = await createReplicator(core); await replicator.open(); return replicator; diff --git a/src/apps/cli/commands/runCommand.ts b/src/apps/cli/commands/runCommand.ts index 535c023..8614b9e 100644 --- a/src/apps/cli/commands/runCommand.ts +++ b/src/apps/cli/commands/runCommand.ts @@ -7,6 +7,8 @@ import { type ObsidianLiveSyncSettings, REMOTE_COUCHDB, REMOTE_MINIO, + type EntryMilestoneInfo, + type EntryDoc, } from "@lib/common/types"; import { ConnectionStringParser } from "@lib/common/ConnectionString"; import { activateRemoteConfiguration, createRemoteConfigurationId } from "@lib/serviceFeatures/remoteConfig"; @@ -18,6 +20,8 @@ import { performFullScan } from "@lib/serviceFeatures/offlineScanner"; import { UnresolvedErrorManager } from "@lib/services/base/UnresolvedErrorManager"; import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; import { fsPromises as fs, path } from "@/apps/cli/node-compat"; +import type { LiveSyncCouchDBReplicator } from "@lib/replication/couchdb/LiveSyncReplicator"; +import type { LiveSyncJournalReplicator } from "@lib/replication/journal/LiveSyncJournalReplicator"; function redactConnectionString(uri: string): string { return uri.replace(/\/\/([^@/]+)@/u, "//***@"); @@ -38,16 +42,20 @@ async function verifyRemoteState( } try { - let milestone: any; + let milestone: EntryMilestoneInfo | false | undefined = undefined; if (settings.remoteType === REMOTE_COUCHDB) { - const dbRet = await (replicator as any).connectRemoteCouchDBWithSetting(settings, false, true); + const dbRet = await (replicator as LiveSyncCouchDBReplicator).connectRemoteCouchDBWithSetting( + settings, + false, + true + ); if (typeof dbRet === "string") { process.stderr.write(`[Verification] Failed to connect to remote CouchDB: ${dbRet}\n`); return false; } milestone = await dbRet.db.get(MILESTONE_DOCID); } else if (settings.remoteType === REMOTE_MINIO) { - milestone = await (replicator as any).client.downloadJson("_00000000-milestone.json"); + milestone = await (replicator as LiveSyncJournalReplicator).client.downloadJson("_00000000-milestone.json"); } if (milestone) { @@ -62,8 +70,9 @@ async function verifyRemoteState( process.stderr.write("[Verification] Milestone document not found on remote.\n"); return false; } - } catch (e: any) { - process.stderr.write(`[Verification] Failed to fetch milestone document: ${e?.message || e}\n`); + } catch (e) { + const message = e instanceof Error ? e.message : String(e); + process.stderr.write(`[Verification] Failed to fetch milestone document: ${message}\n`); return false; } } @@ -93,7 +102,7 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext // 2. Mirror scan to reconcile PouchDB ↔ local filesystem. const errorManager = new UnresolvedErrorManager(core.services.appLifecycle); log("Running mirror scan..."); - const scanOk = await performFullScan(core as any, log, errorManager, false, true); + const scanOk = await performFullScan(core, log, errorManager, false, true); if (!scanOk) { console.error("[Daemon] Mirror scan failed, cannot continue"); return false; @@ -201,7 +210,7 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext } const timeoutSec = parseTimeoutSeconds(options.commandArgs[0], "p2p-peers"); console.error(`[Command] p2p-peers timeout=${timeoutSec}s`); - const peers = await collectPeers(core as any, timeoutSec); + const peers = await collectPeers(core, timeoutSec); if (peers.length > 0) { process.stdout.write(peers.map((peer) => `[peer]\t${peer.peerId}\t${peer.name}`).join("\n") + "\n"); } @@ -218,14 +227,14 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext } const timeoutSec = parseTimeoutSeconds(options.commandArgs[1], "p2p-sync"); console.error(`[Command] p2p-sync peer=${peerToken} timeout=${timeoutSec}s`); - const peer = await syncWithPeer(core as any, peerToken, timeoutSec); + const peer = await syncWithPeer(core, peerToken, timeoutSec); console.error(`[Done] P2P sync completed with ${peer.name} (${peer.peerId})`); return true; } if (options.command === "p2p-host") { console.error("[Command] p2p-host"); - await openP2PHost(core as any); + await openP2PHost(core); console.error("[Ready] P2P host is running. Press Ctrl+C to stop."); await new Promise(() => {}); return true; @@ -438,9 +447,9 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext if (docPath !== targetPath) continue; const filename = path.basename(docPath); - const conflictsText = (doc._conflicts?.length ?? 0) > 0 ? doc._conflicts.join("\n ") : "N/A"; + const conflictsText = (doc._conflicts?.length ?? 0) > 0 ? doc._conflicts?.join("\n ") : "N/A"; const children = "children" in doc ? doc.children : []; - const rawDoc = await core.services.database.localDatabase.getRaw(doc._id, { + const rawDoc = await core.services.database.localDatabase.getRaw(doc._id, { revs_info: true, }); const pastRevisions = (rawDoc._revs_info ?? []) @@ -512,7 +521,7 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext if (revision === revisionToKeep) { continue; } - const resolved = await core.services.conflict.resolveByDeletingRevision(targetPath, revision, "CLI"); + const resolved = await core.services.conflict.resolveByDeletingRevision(targetPath, revision ?? "", "CLI"); if (!resolved) { process.stderr.write(`[Info] Failed to delete revision ${revision} for ${targetPath}\n`); return false; @@ -525,7 +534,7 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext console.error("[Command] mirror"); const log = (msg: unknown) => console.error(`[Mirror] ${msg}`); const errorManager = new UnresolvedErrorManager(core.services.appLifecycle); - return await performFullScan(core as any, log, errorManager, false, true); + return await performFullScan(core, log, errorManager, false, true); } if (options.command === "remote-add") { diff --git a/src/apps/cli/commands/types.ts b/src/apps/cli/commands/types.ts index 8239646..9f71c08 100644 --- a/src/apps/cli/commands/types.ts +++ b/src/apps/cli/commands/types.ts @@ -47,7 +47,7 @@ export interface CLIOptions { export interface CLICommandContext { databasePath: string; vaultPath: string; - core: LiveSyncBaseCore; + core: LiveSyncBaseCore; settingsPath: string; originalSyncSettings: Pick< ObsidianLiveSyncSettings, diff --git a/src/apps/cli/entrypoint.ts b/src/apps/cli/entrypoint.ts index 5c6069c..0e8de12 100644 --- a/src/apps/cli/entrypoint.ts +++ b/src/apps/cli/entrypoint.ts @@ -3,9 +3,11 @@ import * as polyfill from "werift"; import { main } from "./main"; +// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Polyfill const rtcPolyfillCtor = (polyfill as any).RTCPeerConnection; if (typeof (global as any).RTCPeerConnection === "undefined" && typeof rtcPolyfillCtor === "function") { // Fill only the standard WebRTC global in Node CLI runtime. + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Polyfill (global as any).RTCPeerConnection = rtcPolyfillCtor; } diff --git a/src/apps/cli/lib/pouchdb-node.ts b/src/apps/cli/lib/pouchdb-node.ts index 137644e..3309d6a 100644 --- a/src/apps/cli/lib/pouchdb-node.ts +++ b/src/apps/cli/lib/pouchdb-node.ts @@ -25,42 +25,45 @@ type PurgeMultiResult = { }; type PurgeMultiParam = [docId: string, rev$$1: string]; function appendPurgeSeqs(db: PouchDB.Database, docs: PurgeMultiParam[]) { - return db - .get("_local/purges") - .then(function (doc: any) { - for (const [docId, rev$$1] of docs) { - const purgeSeq = doc.purgeSeq + 1; - doc.purges.push({ - docId, - rev: rev$$1, - purgeSeq, - }); - //@ts-ignore : missing type def - if (doc.purges.length > db.purged_infos_limit) { + return ( + db + .get("_local/purges") + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Internal method patching. + .then(function (doc: any) { + for (const [docId, rev$$1] of docs) { + const purgeSeq = doc.purgeSeq + 1; + doc.purges.push({ + docId, + rev: rev$$1, + purgeSeq, + }); //@ts-ignore : missing type def - doc.purges.splice(0, doc.purges.length - db.purged_infos_limit); + if (doc.purges.length > db.purged_infos_limit) { + //@ts-ignore : missing type def + doc.purges.splice(0, doc.purges.length - db.purged_infos_limit); + } + doc.purgeSeq = purgeSeq; } - doc.purgeSeq = purgeSeq; - } - return doc; - }) - .catch(function (err) { - if (err.status !== 404) { - throw err; - } - return { - _id: "_local/purges", - purges: docs.map(([docId, rev$$1], idx) => ({ - docId, - rev: rev$$1, - purgeSeq: idx, - })), - purgeSeq: docs.length, - }; - }) - .then(function (doc) { - return db.put(doc); - }); + return doc; + }) + .catch(function (err) { + if (err.status !== 404) { + throw err; + } + return { + _id: "_local/purges", + purges: docs.map(([docId, rev$$1], idx) => ({ + docId, + rev: rev$$1, + purgeSeq: idx, + })), + purgeSeq: docs.length, + }; + }) + .then(function (doc) { + return db.put(doc); + }) + ); } /** diff --git a/src/apps/cli/main.ts b/src/apps/cli/main.ts index 58eea46..173a3ac 100644 --- a/src/apps/cli/main.ts +++ b/src/apps/cli/main.ts @@ -184,6 +184,7 @@ export function parseArgs(): CLIOptions { break; default: { if (!databasePath) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Set checking if (command === "daemon" && VALID_COMMANDS.has(token as any)) { command = token as CLICommand; break; @@ -195,6 +196,7 @@ export function parseArgs(): CLIOptions { databasePath = token; break; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Set checking if (command === "daemon" && VALID_COMMANDS.has(token as any)) { command = token as CLICommand; break; @@ -239,8 +241,8 @@ async function createDefaultSettingsFile(options: CLIOptions) { try { await fs.stat(targetPath); throw new Error(`Settings file already exists: ${targetPath} (use --force to overwrite)`); - } catch (ex: any) { - if (!(ex && ex?.code === "ENOENT")) { + } catch (ex) { + if (!(ex && (ex as { code?: string })?.code === "ENOENT")) { throw ex; } } @@ -427,7 +429,7 @@ export async function main() { // Create LiveSync core const core = new LiveSyncBaseCore( serviceHubInstance, - (core: LiveSyncBaseCore, serviceHub: InjectableServiceHub) => { + (core: LiveSyncBaseCore, serviceHub: InjectableServiceHub) => { return initialiseServiceModulesCLI(vaultPath, core, serviceHub, ignoreRules, watchEnabled); }, (core) => [], diff --git a/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts b/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts index 9324155..fd3488b 100644 --- a/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts +++ b/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts @@ -19,12 +19,23 @@ import { fsPromises as fs, path, type Stats } from "@/apps/cli/node-compat"; * CLI-specific type guard adapter */ class CLITypeGuardAdapter implements IStorageEventTypeGuardAdapter { - isFile(file: any): file is NodeFile { - return file && typeof file === "object" && "path" in file && "stat" in file && !file.isFolder; + isFile(file: unknown): file is NodeFile { + return !!( + file && + typeof file === "object" && + "path" in file && + "stat" in file && + !(file as { isFolder?: boolean }).isFolder + ); } - isFolder(item: any): item is NodeFolder { - return item && typeof item === "object" && "path" in item && item.isFolder === true; + isFolder(item: unknown): item is NodeFolder { + return !!( + item && + typeof item === "object" && + "path" in item && + (item as { isFolder?: boolean }).isFolder === true + ); } } diff --git a/src/apps/cli/serviceModules/CLIServiceModules.ts b/src/apps/cli/serviceModules/CLIServiceModules.ts index 22e66b5..537658d 100644 --- a/src/apps/cli/serviceModules/CLIServiceModules.ts +++ b/src/apps/cli/serviceModules/CLIServiceModules.ts @@ -22,7 +22,7 @@ import type { IgnoreRules } from "./IgnoreRules"; */ export function initialiseServiceModulesCLI( basePath: string, - core: LiveSyncBaseCore, + core: LiveSyncBaseCore, services: InjectableServiceHub, ignoreRules?: IgnoreRules, watchEnabled: boolean = false @@ -81,7 +81,7 @@ export function initialiseServiceModulesCLI( }); // File handler (platform-independent) - const fileHandler = new (ServiceFileHandler as any)({ + const fileHandler = new ServiceFileHandler({ API: services.API, databaseFileAccess: databaseFileAccess, conflict: services.conflict, diff --git a/src/apps/cli/services/NodeKeyValueDBService.ts b/src/apps/cli/services/NodeKeyValueDBService.ts index d64768d..724e79b 100644 --- a/src/apps/cli/services/NodeKeyValueDBService.ts +++ b/src/apps/cli/services/NodeKeyValueDBService.ts @@ -178,7 +178,7 @@ export class NodeKeyValueDBService implements IKeyValueDBService { private _kvDB: KeyValueDatabase | undefined; - private _simpleStore: SimpleStore | undefined; + private _simpleStore: SimpleStore | undefined; private filePath: string; private _log = createInstanceLogFunction("NodeKeyValueDBService"); @@ -248,7 +248,7 @@ export class NodeKeyValueDBService if (!(await this.openKeyValueDB())) { return false; } - this._simpleStore = this.openSimpleStore("os"); + this._simpleStore = this.openSimpleStore("os"); return true; } @@ -264,7 +264,7 @@ export class NodeKeyValueDBService get: async (key: string): Promise => { return await getDB().get(`${prefix}${key}`); }, - set: async (key: string, value: any): Promise => { + set: async (key: string, value: unknown): Promise => { await getDB().set(`${prefix}${key}`, value); }, delete: async (key: string): Promise => { diff --git a/src/apps/cli/services/NodeLocalStorage.ts b/src/apps/cli/services/NodeLocalStorage.ts index a62df61..5a2bb45 100644 --- a/src/apps/cli/services/NodeLocalStorage.ts +++ b/src/apps/cli/services/NodeLocalStorage.ts @@ -83,7 +83,9 @@ function createNodeLocalStorageShim(): LocalStorageShape { } export function ensureGlobalNodeLocalStorage() { + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Node.js global object manipulation if (!("localStorage" in global) || typeof (global as any).localStorage?.getItem !== "function") { + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Node.js global object access (global as any).localStorage = createNodeLocalStorageShim(); } } diff --git a/src/apps/cli/services/NodeServiceHub.ts b/src/apps/cli/services/NodeServiceHub.ts index 2344bdd..e3aea9d 100644 --- a/src/apps/cli/services/NodeServiceHub.ts +++ b/src/apps/cli/services/NodeServiceHub.ts @@ -25,6 +25,7 @@ import { NodeSettingService } from "./NodeSettingService"; import { DatabaseService } from "@lib/services/base/DatabaseService"; import type { ObsidianLiveSyncSettings } from "@lib/common/types"; import { path as nodePath } from "@/apps/cli/node-compat"; +import type { KeyValueDBService } from "@lib/services/base/KeyValueDBService"; export class NodeServiceContext extends ServiceContext { databasePath: string; @@ -197,10 +198,10 @@ export class NodeServiceHub extends InjectableServ path, API, config, - keyValueDB: keyValueDB as any, + keyValueDB: keyValueDB as unknown as KeyValueDBService, control, }; - + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- (Forcibly ) super(context, serviceInstancesToInit as any); } } diff --git a/src/apps/webapp/bootstrap.ts b/src/apps/webapp/bootstrap.ts index a6d9800..15e18cb 100644 --- a/src/apps/webapp/bootstrap.ts +++ b/src/apps/webapp/bootstrap.ts @@ -133,7 +133,7 @@ compatGlobal.addEventListener("load", async () => { compatGlobal.addEventListener("beforeunload", () => { void app?.shutdown(); }); - +// eslint-disable-next-line @typescript-eslint/no-explicit-any -- patching (compatGlobal as any).livesyncApp = { getApp: () => app, historyStore, diff --git a/src/apps/webapp/main.ts b/src/apps/webapp/main.ts index f508028..f53861a 100644 --- a/src/apps/webapp/main.ts +++ b/src/apps/webapp/main.ts @@ -50,7 +50,7 @@ const DEFAULT_SETTINGS: Partial = { class LiveSyncWebApp { private rootHandle: FileSystemDirectoryHandle; - private core: LiveSyncBaseCore | null = null; + private core: LiveSyncBaseCore | null = null; private serviceHub: BrowserServiceHub | null = null; constructor(rootHandle: FileSystemDirectoryHandle) { @@ -107,7 +107,7 @@ class LiveSyncWebApp { }); // Create LiveSync core - this.core = new LiveSyncBaseCore( + this.core = new LiveSyncBaseCore( this.serviceHub, (core, serviceHub) => { return initialiseServiceModulesFSAPI(this.rootHandle, core, serviceHub); @@ -127,7 +127,7 @@ class LiveSyncWebApp { // new ModuleReplicatorP2P(core), // Register P2P replicator for CLI (useP2PReplicator is not used here) new SetupManager(core), ], - () => [], // No add-ons + () => [] as never[], // No add-ons (core) => { useOfflineScanner(core); useRedFlagFeatures(core); @@ -205,6 +205,7 @@ class LiveSyncWebApp { } // Scan the directory to populate file cache + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Accessing private service modules const fileAccess = (this.core as any)._serviceModules?.storageAccess?.vaultAccess; if (fileAccess?.fsapiAdapter) { console.log("[Scanning] Scanning vault directory..."); @@ -223,6 +224,7 @@ class LiveSyncWebApp { console.log("[Shutdown] Shutting down..."); // Stop file watching + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Accessing private service modules const storageEventManager = (this.core as any)._serviceModules?.storageAccess?.storageEventManager; if (storageEventManager?.cleanup) { await storageEventManager.cleanup(); diff --git a/src/apps/webapp/managers/FSAPIStorageEventManagerAdapter.ts b/src/apps/webapp/managers/FSAPIStorageEventManagerAdapter.ts index 4010c5c..7ae81fb 100644 --- a/src/apps/webapp/managers/FSAPIStorageEventManagerAdapter.ts +++ b/src/apps/webapp/managers/FSAPIStorageEventManagerAdapter.ts @@ -17,14 +17,25 @@ import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; * FileSystem API-specific type guard adapter */ class FSAPITypeGuardAdapter implements IStorageEventTypeGuardAdapter { - isFile(file: any): file is FSAPIFile { - return ( - file && typeof file === "object" && "path" in file && "stat" in file && "handle" in file && !file.isFolder + isFile(file: unknown): file is FSAPIFile { + return !!( + file && + typeof file === "object" && + "path" in file && + "stat" in file && + "handle" in file && + !(file as { isFolder?: boolean }).isFolder ); } - isFolder(item: any): item is FSAPIFolder { - return item && typeof item === "object" && "path" in item && item.isFolder === true && "handle" in item; + isFolder(item: unknown): item is FSAPIFolder { + return !!( + item && + typeof item === "object" && + "path" in item && + (item as { isFolder?: boolean }).isFolder === true && + "handle" in item + ); } } @@ -144,12 +155,14 @@ class FSAPIConverterAdapter implements IStorageEventConverterAdapter * FileSystem API-specific watch adapter using FileSystemObserver (Chrome only) */ class FSAPIWatchAdapter implements IStorageEventWatchAdapter { + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Accessing private service modules private observer: any = null; // FileSystemObserver type constructor(private rootHandle: FileSystemDirectoryHandle) {} async beginWatch(handlers: IStorageEventWatchHandlers): Promise { // Use FileSystemObserver if available (Chrome 124+) + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Accessing global FileSystemObserver if (typeof (compatGlobal as any).FileSystemObserver === "undefined") { console.log("[FSAPIWatchAdapter] FileSystemObserver not available, file watching disabled"); console.log("[FSAPIWatchAdapter] Consider using Chrome 124+ for real-time file watching"); @@ -157,8 +170,10 @@ class FSAPIWatchAdapter implements IStorageEventWatchAdapter { } try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Accessing private service modules const FileSystemObserver = (compatGlobal as any).FileSystemObserver; + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Accessing private service modules this.observer = new FileSystemObserver(async (records: any[]) => { for (const record of records) { const changedHandle = record.changedHandle; @@ -206,7 +221,7 @@ class FSAPIWatchAdapter implements IStorageEventWatchAdapter { ctime: Date.now(), type: "file" as const, }, - handle: null as any, + handle: null as unknown as FileSystemFileHandle, // No handle available for disappeared files }; await handlers.onDelete(fileInfo, undefined); } else if (type === "moved") { diff --git a/src/apps/webapp/managers/StorageEventManagerFSAPI.ts b/src/apps/webapp/managers/StorageEventManagerFSAPI.ts index fb2761f..cda0749 100644 --- a/src/apps/webapp/managers/StorageEventManagerFSAPI.ts +++ b/src/apps/webapp/managers/StorageEventManagerFSAPI.ts @@ -30,7 +30,7 @@ export class StorageEventManagerFSAPI extends StorageEventManagerBase, + core: LiveSyncBaseCore, services: InjectableServiceHub ): ServiceModules { const storageAccessManager = new StorageAccessManager(); @@ -67,7 +67,7 @@ export function initialiseServiceModulesFSAPI( }); // File handler (platform-independent) - const fileHandler = new (ServiceFileHandler as any)({ + const fileHandler = new ServiceFileHandler({ API: services.API, databaseFileAccess: databaseFileAccess, conflict: services.conflict, diff --git a/src/apps/webpeer/src/P2PReplicatorShim.ts b/src/apps/webpeer/src/P2PReplicatorShim.ts index d31ac5a..7c070ab 100644 --- a/src/apps/webpeer/src/P2PReplicatorShim.ts +++ b/src/apps/webpeer/src/P2PReplicatorShim.ts @@ -10,7 +10,7 @@ import { import { eventHub } from "@lib/hub/hub"; import type { Confirm } from "@lib/interfaces/Confirm"; -import { LOG_LEVEL_NOTICE, Logger } from "@lib/common/logger"; +import { LOG_LEVEL_NOTICE, Logger, type LOG_LEVEL } from "@lib/common/logger"; import { EVENT_P2P_PEER_SHOW_EXTRA_MENU, type PeerStatus, @@ -65,7 +65,7 @@ export class P2PReplicatorShim implements P2PReplicatorBase { } return this.db; } - _simpleStore!: SimpleStore; + _simpleStore!: SimpleStore; async closeDB() { if (this.db) { @@ -82,6 +82,7 @@ export class P2PReplicatorShim implements P2PReplicatorBase { replicator, p2pLogCollector, storeP2PStatusLine: p2pStatusLine, + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- hacky way. //TODO: check it later } = useP2PReplicator({ services: this.services } as any); this._liveSyncReplicator = replicator; this.p2pLogCollector = p2pLogCollector; @@ -97,15 +98,15 @@ export class P2PReplicatorShim implements P2PReplicatorBase { (this.services.API as BrowserAPIService).getSystemVaultName.setHandler( () => "p2p-livesync-web-peer" ); - const repStore = SimpleStoreIDBv2.open("p2p-livesync-web-peer"); + const repStore = SimpleStoreIDBv2.open("p2p-livesync-web-peer"); this._simpleStore = repStore; let _settings = { ...P2P_DEFAULT_SETTINGS, additionalSuffixOfDatabaseName: "" } as ObsidianLiveSyncSettings; - this.services.setting.settings = _settings as any; - (this.services.setting as InjectableSettingService).saveData.setHandler(async (data) => { + this.services.setting.settings = _settings as ObsidianLiveSyncSettings; + (this.services.setting as InjectableSettingService).saveData.setHandler(async (data) => { await repStore.set("settings", data); eventHub.emitEvent(EVENT_SETTING_SAVED, data); }); - (this.services.setting as InjectableSettingService).loadData.setHandler(async () => { + (this.services.setting as InjectableSettingService).loadData.setHandler(async () => { const settings = { ..._settings, ...((await repStore.get("settings")) as ObsidianLiveSyncSettings) }; return settings; }); @@ -147,7 +148,7 @@ export class P2PReplicatorShim implements P2PReplicatorBase { return this; } - _log(msg: any, level?: any): void { + _log(msg: unknown, level?: LOG_LEVEL): void { Logger(msg, level); } _notice(msg: string, key?: string): void { @@ -156,7 +157,7 @@ export class P2PReplicatorShim implements P2PReplicatorBase { getSettings(): P2PSyncSetting { return this.settings; } - simpleStore(): SimpleStore { + simpleStore(): SimpleStore { return this._simpleStore; } handleReplicatedDocuments(_docs: EntryDoc[]): Promise { diff --git a/src/common/utils.ts b/src/common/utils.ts index cafa3f3..573bb64 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -290,7 +290,6 @@ export function useMemo( return value; } -// const _static = new Map(); const _staticObj = new Map< string, { diff --git a/utilsdeno/types-add-ignore.ts b/utilsdeno/types-add-ignore.ts index 04620fb..2ef1573 100644 --- a/utilsdeno/types-add-ignore.ts +++ b/utilsdeno/types-add-ignore.ts @@ -29,14 +29,60 @@ function processFile(filePath: string, origin: string, repoHash: string): string name: "EventEmitter", isExported: false, methods: [ - { name: "on", parameters: [{ name: "event", type: "string | symbol" }, { name: "listener", type: "(...args: any[]) => void" }], returnType: "this" }, - { name: "once", parameters: [{ name: "event", type: "string | symbol" }, { name: "listener", type: "(...args: any[]) => void" }], returnType: "this" }, - { name: "off", parameters: [{ name: "event", type: "string | symbol" }, { name: "listener", type: "(...args: any[]) => void" }], returnType: "this" }, - { name: "emit", parameters: [{ name: "event", type: "string | symbol" }, { name: "args", isRestParameter: true, type: "any[]" }], returnType: "boolean" }, - { name: "addListener", parameters: [{ name: "event", type: "string | symbol" }, { name: "listener", type: "(...args: any[]) => void" }], returnType: "this" }, - { name: "removeListener", parameters: [{ name: "event", type: "string | symbol" }, { name: "listener", type: "(...args: any[]) => void" }], returnType: "this" }, - { name: "removeAllListeners", parameters: [{ name: "event", isOptional: true, type: "string | symbol" }], returnType: "this" }, - ] + { + name: "on", + parameters: [ + { name: "event", type: "string | symbol" }, + { name: "listener", type: "(...args: any[]) => void" }, + ], + returnType: "this", + }, + { + name: "once", + parameters: [ + { name: "event", type: "string | symbol" }, + { name: "listener", type: "(...args: any[]) => void" }, + ], + returnType: "this", + }, + { + name: "off", + parameters: [ + { name: "event", type: "string | symbol" }, + { name: "listener", type: "(...args: any[]) => void" }, + ], + returnType: "this", + }, + { + name: "emit", + parameters: [ + { name: "event", type: "string | symbol" }, + { name: "args", isRestParameter: true, type: "any[]" }, + ], + returnType: "boolean", + }, + { + name: "addListener", + parameters: [ + { name: "event", type: "string | symbol" }, + { name: "listener", type: "(...args: any[]) => void" }, + ], + returnType: "this", + }, + { + name: "removeListener", + parameters: [ + { name: "event", type: "string | symbol" }, + { name: "listener", type: "(...args: any[]) => void" }, + ], + returnType: "this", + }, + { + name: "removeAllListeners", + parameters: [{ name: "event", isOptional: true, type: "string | symbol" }], + returnType: "this", + }, + ], }); updated = true; } @@ -110,7 +156,8 @@ function processFile(filePath: string, origin: string, repoHash: string): string const line = lines[lineIndex]; if (!line) continue; if (line.includes("eslint-disable-line") || line.includes("eslint-disable-next-line")) continue; - lines[lineIndex] = `${line} // eslint-disable-line @typescript-eslint/no-empty-object-type, @typescript-eslint/ban-types -- Empty object type`; + lines[lineIndex] = + `${line} // eslint-disable-line @typescript-eslint/no-empty-object-type, @typescript-eslint/ban-types -- Empty object type`; updated = true; } @@ -119,7 +166,8 @@ function processFile(filePath: string, origin: string, repoHash: string): string const line = lines[lineIndex]; if (!line) continue; if (line.includes("eslint-disable-line") || line.includes("eslint-disable-next-line")) continue; - lines[lineIndex] = `${line} // eslint-disable-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-empty-interface -- Empty interface`; + lines[lineIndex] = + `${line} // eslint-disable-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-empty-interface -- Empty interface`; updated = true; } @@ -128,7 +176,8 @@ function processFile(filePath: string, origin: string, repoHash: string): string const line = lines[lineIndex]; if (!line) continue; if (line.includes("eslint-disable-line") || line.includes("eslint-disable-next-line")) continue; - lines[lineIndex] = `${line} // eslint-disable-line @typescript-eslint/no-duplicate-enum-values -- Duplicate enum value`; + lines[lineIndex] = + `${line} // eslint-disable-line @typescript-eslint/no-duplicate-enum-values -- Duplicate enum value`; updated = true; }