Fix types

This commit is contained in:
vorotamoroz
2026-06-19 07:52:04 +01:00
parent b2c6916ac7
commit 42954fcf68
23 changed files with 219 additions and 111 deletions
+1
View File
@@ -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\" ",
@@ -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<NodeFile, NodeF
path: folder.path,
isFolder: true,
children: [],
parent: path.dirname(folder.path) as any,
parent: path.dirname(folder.path) as FilePath,
};
}
}
+15 -4
View File
@@ -5,11 +5,22 @@ import type { NodeFile, NodeFolder } from "./NodeTypes";
* Type guard adapter implementation for Node.js
*/
export class NodeTypeGuardAdapter implements ITypeGuardAdapter<NodeFile, NodeFolder> {
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
);
}
}
+4 -4
View File
@@ -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<NodeFile> {
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<NodeFile> {
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<NodeFile> {
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;
}
+6 -6
View File
@@ -21,7 +21,7 @@ export function parseTimeoutSeconds(value: string, commandName: string): number
return timeoutSec;
}
function validateP2PSettings(core: LiveSyncBaseCore<ServiceContext, any>) {
function validateP2PSettings(core: LiveSyncBaseCore<ServiceContext, never>) {
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<ServiceContext, any>) {
settings.P2P_IsHeadless = true;
}
async function createReplicator(core: LiveSyncBaseCore<ServiceContext, any>): Promise<LiveSyncTrysteroReplicator> {
async function createReplicator(core: LiveSyncBaseCore<ServiceContext, never>): Promise<LiveSyncTrysteroReplicator> {
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<ServiceContext, any>,
core: LiveSyncBaseCore<ServiceContext, never>,
timeoutSec: number
): Promise<CLIP2PPeer[]> {
const replicator = await createReplicator(core);
@@ -81,7 +81,7 @@ function resolvePeer(peers: CLIP2PPeer[], peerToken: string): CLIP2PPeer | undef
}
export async function syncWithPeer(
core: LiveSyncBaseCore<ServiceContext, any>,
core: LiveSyncBaseCore<ServiceContext, never>,
peerToken: string,
timeoutSec: number
): Promise<CLIP2PPeer> {
@@ -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<ServiceContext, any>): Promise<LiveSyncTrysteroReplicator> {
export async function openP2PHost(core: LiveSyncBaseCore<ServiceContext, never>): Promise<LiveSyncTrysteroReplicator> {
const replicator = await createReplicator(core);
await replicator.open();
return replicator;
+22 -13
View File
@@ -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<any>(doc._id, {
const rawDoc = await core.services.database.localDatabase.getRaw<EntryDoc>(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") {
+1 -1
View File
@@ -47,7 +47,7 @@ export interface CLIOptions {
export interface CLICommandContext {
databasePath: string;
vaultPath: string;
core: LiveSyncBaseCore<ServiceContext, any>;
core: LiveSyncBaseCore<ServiceContext, never>;
settingsPath: string;
originalSyncSettings: Pick<
ObsidianLiveSyncSettings,
+2
View File
@@ -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;
}
+37 -34
View File
@@ -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);
})
);
}
/**
+5 -3
View File
@@ -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<NodeServiceContext, any>, serviceHub: InjectableServiceHub<NodeServiceContext>) => {
(core: LiveSyncBaseCore<NodeServiceContext, never>, serviceHub: InjectableServiceHub<NodeServiceContext>) => {
return initialiseServiceModulesCLI(vaultPath, core, serviceHub, ignoreRules, watchEnabled);
},
(core) => [],
@@ -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<NodeFile, NodeFolder> {
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
);
}
}
@@ -22,7 +22,7 @@ import type { IgnoreRules } from "./IgnoreRules";
*/
export function initialiseServiceModulesCLI(
basePath: string,
core: LiveSyncBaseCore<ServiceContext, any>,
core: LiveSyncBaseCore<ServiceContext, never>,
services: InjectableServiceHub<ServiceContext>,
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,
@@ -178,7 +178,7 @@ export class NodeKeyValueDBService<T extends ServiceContext = ServiceContext>
implements IKeyValueDBService
{
private _kvDB: KeyValueDatabase | undefined;
private _simpleStore: SimpleStore<any> | undefined;
private _simpleStore: SimpleStore<unknown> | undefined;
private filePath: string;
private _log = createInstanceLogFunction("NodeKeyValueDBService");
@@ -248,7 +248,7 @@ export class NodeKeyValueDBService<T extends ServiceContext = ServiceContext>
if (!(await this.openKeyValueDB())) {
return false;
}
this._simpleStore = this.openSimpleStore<any>("os");
this._simpleStore = this.openSimpleStore<unknown>("os");
return true;
}
@@ -264,7 +264,7 @@ export class NodeKeyValueDBService<T extends ServiceContext = ServiceContext>
get: async (key: string): Promise<T> => {
return await getDB().get(`${prefix}${key}`);
},
set: async (key: string, value: any): Promise<void> => {
set: async (key: string, value: unknown): Promise<void> => {
await getDB().set(`${prefix}${key}`, value);
},
delete: async (key: string): Promise<void> => {
@@ -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();
}
}
+3 -2
View File
@@ -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<T extends NodeServiceContext> extends InjectableServ
path,
API,
config,
keyValueDB: keyValueDB as any,
keyValueDB: keyValueDB as unknown as KeyValueDBService<T>,
control,
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- (Forcibly )
super(context, serviceInstancesToInit as any);
}
}
+1 -1
View File
@@ -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,
+5 -3
View File
@@ -50,7 +50,7 @@ const DEFAULT_SETTINGS: Partial<ObsidianLiveSyncSettings> = {
class LiveSyncWebApp {
private rootHandle: FileSystemDirectoryHandle;
private core: LiveSyncBaseCore<ServiceContext, any> | null = null;
private core: LiveSyncBaseCore<ServiceContext, never> | null = null;
private serviceHub: BrowserServiceHub<ServiceContext> | null = null;
constructor(rootHandle: FileSystemDirectoryHandle) {
@@ -107,7 +107,7 @@ class LiveSyncWebApp {
});
// Create LiveSync core
this.core = new LiveSyncBaseCore(
this.core = new LiveSyncBaseCore<ServiceContext, never>(
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();
@@ -17,14 +17,25 @@ import { compatGlobal } from "@lib/common/coreEnvFunctions.ts";
* FileSystem API-specific type guard adapter
*/
class FSAPITypeGuardAdapter implements IStorageEventTypeGuardAdapter<FSAPIFile, FSAPIFolder> {
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<FSAPIFile>
* 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<void> {
// 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") {
@@ -30,7 +30,7 @@ export class StorageEventManagerFSAPI extends StorageEventManagerBase<FSAPIStora
async cleanup() {
// Stop file watching
if (this.fsapiAdapter?.watch) {
await (this.fsapiAdapter.watch as any).stopWatch?.();
await this.fsapiAdapter.watch.stopWatch?.();
}
}
}
@@ -22,7 +22,7 @@ import { ServiceFileHandler } from "@/serviceModules/FileHandler";
*/
export function initialiseServiceModulesFSAPI(
rootHandle: FileSystemDirectoryHandle,
core: LiveSyncBaseCore<ServiceContext, any>,
core: LiveSyncBaseCore<ServiceContext, never>,
services: InjectableServiceHub<ServiceContext>
): 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,
+9 -8
View File
@@ -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<any>;
_simpleStore!: SimpleStore<unknown>;
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<ServiceContext>).getSystemVaultName.setHandler(
() => "p2p-livesync-web-peer"
);
const repStore = SimpleStoreIDBv2.open<any>("p2p-livesync-web-peer");
const repStore = SimpleStoreIDBv2.open<unknown>("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<any>).saveData.setHandler(async (data) => {
this.services.setting.settings = _settings as ObsidianLiveSyncSettings;
(this.services.setting as InjectableSettingService<ServiceContext>).saveData.setHandler(async (data) => {
await repStore.set("settings", data);
eventHub.emitEvent(EVENT_SETTING_SAVED, data);
});
(this.services.setting as InjectableSettingService<any>).loadData.setHandler(async () => {
(this.services.setting as InjectableSettingService<ServiceContext>).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<any> {
simpleStore(): SimpleStore<unknown> {
return this._simpleStore;
}
handleReplicatedDocuments(_docs: EntryDoc[]): Promise<boolean> {
-1
View File
@@ -290,7 +290,6 @@ export function useMemo<T>(
return value;
}
// const _static = new Map<string, any>();
const _staticObj = new Map<
string,
{
+60 -11
View File
@@ -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;
}