Compare commits

..

2 Commits

Author SHA1 Message Date
vorotamoroz
559c3f351b feat: add unit tests for replicateResultProcessor and refactor replicator logging
- Introduced unit tests for the replicateResultProcessor, covering various scenarios including document enqueuing, snapshot handling, and processing of non-document changes.
- Refactored replicator to utilize a logging function from the host API instead of a global logger, enhancing log management.
- Updated mismatchedTweaksResolver to include logging through the host API, ensuring consistent logging practices across the application.
- Adjusted tests to mock the new logging behavior and verify log outputs.
2026-06-26 09:36:48 +00:00
vorotamoroz
f954448ef8 Challenge: Make all modules testable, mockable and spied on! 2026-06-26 09:30:34 +01:00
240 changed files with 19926 additions and 5004 deletions

View File

@@ -37,6 +37,7 @@ export declare class LiveSyncBaseCore<T extends ServiceContext = ServiceContext,
*/
_services: InjectableServiceHub<T> | undefined;
get services(): InjectableServiceHub<T>;
get context(): T;
/**
* Service Modules
*/

View File

@@ -1,6 +1,6 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type PluginManifest, TFile } from "@/deps.ts";
import type { PluginManifest, TFile } from "@/deps.ts";
import { type DatabaseEntry, type EntryBody, type FilePath } from "@lib/common/types.ts";
export type { CacheData, FileEventItem } from "@lib/common/types.ts";
export interface PluginDataEntry extends DatabaseEntry {

View File

@@ -1,147 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type PluginManifest } from "@/deps.ts";
import type { EntryDoc, LoadedEntry, FilePathWithPrefix, FilePath, AnyEntry } from "@lib/common/types.ts";
import { LiveSyncCommands } from "@/features/LiveSyncCommands.ts";
import { PeriodicProcessor } from "@/common/PeriodicProcessor.ts";
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
import type ObsidianLiveSyncPlugin from "@/main.ts";
import { PluginDialogModal } from "./PluginDialogModal.ts";
import type { InjectableServiceHub } from "@lib/services/InjectableServices.ts";
import type { LiveSyncCore } from "@/main.ts";
declare global {
interface OPTIONAL_SYNC_FEATURES {
DISABLE: "DISABLE";
CUSTOMIZE: "CUSTOMIZE";
DISABLE_CUSTOM: "DISABLE_CUSTOM";
}
}
export declare const pluginList: import("svelte/store").Writable<PluginDataExDisplay[]>;
export declare const pluginIsEnumerating: import("svelte/store").Writable<boolean>;
export declare const pluginV2Progress: import("svelte/store").Writable<number>;
export type PluginDataExFile = {
filename: string;
data: string[];
mtime: number;
size: number;
version?: string;
hash?: string;
displayName?: string;
};
export interface IPluginDataExDisplay {
documentPath: FilePathWithPrefix;
category: string;
name: string;
term: string;
displayName?: string;
files: (LoadedEntryPluginDataExFile | PluginDataExFile)[];
version?: string;
mtime: number;
}
export type PluginDataExDisplay = {
documentPath: FilePathWithPrefix;
category: string;
name: string;
term: string;
displayName?: string;
files: PluginDataExFile[];
version?: string;
mtime: number;
};
type LoadedEntryPluginDataExFile = LoadedEntry & PluginDataExFile;
export declare const pluginManifests: Map<string, PluginManifest>;
export declare const pluginManifestStore: import("svelte/store").Writable<Map<string, PluginManifest>>;
export declare class PluginDataExDisplayV2 {
documentPath: FilePathWithPrefix;
category: string;
term: string;
files: LoadedEntryPluginDataExFile[];
name: string;
confKey: string;
constructor(data: IPluginDataExDisplay);
setFile(file: LoadedEntryPluginDataExFile): Promise<void>;
deleteFile(filename: string): void;
_displayName: string | undefined;
_version: string | undefined;
applyLoadedManifest(): void;
get displayName(): string;
get version(): string | undefined;
get mtime(): number;
}
export type PluginDataEx = {
documentPath?: FilePathWithPrefix;
category: string;
name: string;
displayName?: string;
term: string;
files: PluginDataExFile[];
version?: string;
mtime: number;
};
export declare class ConfigSync extends LiveSyncCommands {
constructor(plugin: ObsidianLiveSyncPlugin, core: LiveSyncCore);
get configDir(): string;
get kvDB(): import("../../lib/src/interfaces/KeyValueDatabase.ts").KeyValueDatabase;
get useV2(): boolean;
get useSyncPluginEtc(): boolean;
isThisModuleEnabled(): boolean;
pluginDialog?: PluginDialogModal;
periodicPluginSweepProcessor: PeriodicProcessor;
pluginList: IPluginDataExDisplay[];
showPluginSyncModal(): void;
hidePluginSyncModal(): void;
onunload(): void;
addRibbonIcon: (icon: string, title: string, callback: (evt: MouseEvent) => unknown) => HTMLElement;
onload(): void;
getFileCategory(filePath: string): "CONFIG" | "THEME" | "SNIPPET" | "PLUGIN_MAIN" | "PLUGIN_ETC" | "PLUGIN_DATA" | "";
isTargetPath(filePath: string): boolean;
private _everyOnDatabaseInitialized;
_everyBeforeReplicate(showNotice: boolean): Promise<boolean>;
_everyOnResumeProcess(): Promise<boolean>;
_everyAfterResumeProcess(): Promise<boolean>;
reloadPluginList(showMessage: boolean): Promise<void>;
loadPluginData(path: FilePathWithPrefix): Promise<PluginDataExDisplay | false>;
pluginScanProcessor: QueueProcessor<AnyEntry, never>;
pluginScanProcessorV2: QueueProcessor<AnyEntry, never>;
filenameToUnifiedKey(path: string, termOverRide?: string): FilePathWithPrefix;
filenameWithUnifiedKey(path: string, termOverRide?: string): FilePathWithPrefix;
unifiedKeyPrefixOfTerminal(termOverRide?: string): FilePathWithPrefix;
parseUnifiedPath(unifiedPath: FilePathWithPrefix): {
category: string;
device: string;
key: string;
filename: string;
pathV1: FilePathWithPrefix;
};
loadedManifest_mTime: Map<string, number>;
createPluginDataExFileV2(unifiedPathV2: FilePathWithPrefix, loaded?: LoadedEntry): Promise<false | LoadedEntryPluginDataExFile>;
createPluginDataFromV2(unifiedPathV2: FilePathWithPrefix): PluginDataExDisplayV2 | undefined;
updatingV2Count: number;
updatePluginListV2(showMessage: boolean, unifiedFilenameWithKey: FilePathWithPrefix): Promise<void>;
migrateV1ToV2(showMessage: boolean, entry: AnyEntry): Promise<void>;
updatePluginList(showMessage: boolean, updatedDocumentPath?: FilePathWithPrefix): Promise<void>;
compareUsingDisplayData(dataA: IPluginDataExDisplay, dataB: IPluginDataExDisplay, compareEach?: boolean): Promise<boolean>;
applyDataV2(data: PluginDataExDisplayV2, content?: string): Promise<boolean>;
applyData(data: IPluginDataExDisplay, content?: string): Promise<boolean>;
deleteData(data: PluginDataEx): Promise<boolean>;
_anyModuleParsedReplicationResultItem(docs: PouchDB.Core.ExistingDocument<EntryDoc>): Promise<boolean>;
_everyRealizeSettingSyncMode(): Promise<boolean>;
recentProcessedInternalFiles: string[];
makeEntryFromFile(path: FilePath): Promise<false | PluginDataExFile>;
storeCustomisationFileV2(path: FilePath, term: string, force?: boolean): Promise<boolean | PouchDB.Core.Response | undefined>;
storeCustomizationFiles(path: FilePath, termOverRide?: string): Promise<boolean | PouchDB.Core.Response | undefined>;
_anyProcessOptionalFileEvent(path: FilePath): Promise<boolean>;
watchVaultRawEventsAsync(path: FilePath): Promise<boolean>;
scanAllConfigFiles(showMessage: boolean): Promise<void>;
deleteConfigOnDatabase(prefixedFileName: FilePathWithPrefix, forceWrite?: boolean): Promise<boolean>;
scanInternalFiles(): Promise<FilePath[]>;
private _allAskUsingOptionalSyncFeature;
private __askHiddenFileConfiguration;
_anyGetOptionalConflictCheckMethod(path: FilePathWithPrefix): Promise<boolean | "newer">;
private _allSuspendExtraSync;
private _allConfigureOptionalSyncFeature;
configureHiddenFileSync(mode: keyof OPTIONAL_SYNC_FEATURES): Promise<void>;
getFiles(path: string, lastDepth: number): Promise<string[]>;
onBindFunction(core: LiveSyncCore, services: InjectableServiceHub): void;
}
export {};

View File

@@ -1,59 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type DocumentID, type EntryDoc, type EntryLeaf } from "@lib/common/types";
import { LiveSyncCommands } from "@/features/LiveSyncCommands";
type ChunkID = DocumentID;
type NoteDocumentID = DocumentID;
type Rev = string;
type ChunkUsageMap = Map<NoteDocumentID, Map<Rev, Set<ChunkID>>>;
export declare class LocalDatabaseMaintenance extends LiveSyncCommands {
onunload(): void;
onload(): void | Promise<void>;
allChunks(includeDeleted?: boolean): Promise<{
used: Set<string>;
existing: Map<string, EntryLeaf>;
}>;
get database(): PouchDB.Database<EntryDoc>;
clearHash(): void;
confirm(title: string, message: string, affirmative?: string, negative?: string): Promise<boolean>;
isAvailable(): boolean;
/**
* Resurrect deleted chunks that are still used in the database.
*/
resurrectChunks(): Promise<void>;
/**
* Commit deletion of files that are marked as deleted.
* This method makes the deletion permanent, and the files will not be recovered.
* After this, chunks that are used in the deleted files become ready for compaction.
*/
commitFileDeletion(): Promise<void>;
/**
* Commit deletion of chunks that are not used in the database.
* This method makes the deletion permanent, and the chunks will not be recovered if the database run compaction.
* After this, the database can shrink the database size by compaction.
* It is recommended to compact the database after this operation (History should be kept once before compaction).
*/
commitChunkDeletion(): Promise<void>;
/**
* Compact the database.
* This method removes all deleted chunks that are not used in the database.
* Make sure all devices are synchronized before running this method.
*/
markUnusedChunks(): Promise<void>;
removeUnusedChunks(): Promise<void>;
scanUnusedChunks(): Promise<{
chunkSet: Set<DocumentID>;
chunkUsageMap: ChunkUsageMap;
unusedSet: Set<DocumentID>;
}>;
/**
* Track changes in the database and update the chunk usage map for garbage collection.
* Note that this only able to perform without Fetch chunks on demand.
*/
trackChanges(fromStart?: boolean, showNotice?: boolean): Promise<void>;
performGC(showingNotice?: boolean): Promise<void>;
analyseDatabase(): Promise<void>;
compactDatabase(): Promise<void>;
gcv3(): Promise<void>;
}
export {};

View File

@@ -1,10 +1,9 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { Plugin, type App, type PluginManifest } from "./deps";
import { LiveSyncCommands } from "./features/LiveSyncCommands.ts";
import type { ObsidianServiceContext } from "@lib/services/implements/obsidian/ObsidianServiceContext.ts";
import { LiveSyncBaseCore } from "./LiveSyncBaseCore.ts";
export type LiveSyncCore = LiveSyncBaseCore<ObsidianServiceContext, LiveSyncCommands>;
import type { LiveSyncCore } from "./types.ts";
export type { LiveSyncCore, NecessaryObsidianFeature, ObsidianServiceFeatureFunction } from "./types.ts";
export { createObsidianServiceFeature } from "./types.ts";
export default class ObsidianLiveSyncPlugin extends Plugin {
core: LiveSyncCore;
/**

View File

@@ -1,16 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { PeriodicProcessor } from "@/common/PeriodicProcessor";
import type { LiveSyncCore } from "@/main";
import { AbstractModule } from "@/modules/AbstractModule";
export declare class ModulePeriodicProcess extends AbstractModule {
periodicSyncProcessor: PeriodicProcessor;
disablePeriodic(): Promise<boolean>;
resumePeriodic(): Promise<boolean>;
private _allOnUnload;
private _everyBeforeRealizeSetting;
private _everyBeforeSuspendProcess;
private _everyAfterResumeProcess;
private _everyAfterRealizeSetting;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -1,25 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { AbstractModule } from "@/modules/AbstractModule";
import { type EntryDoc, type RemoteType } from "@lib/common/types";
import type { LiveSyncCore } from "@/main";
import { ReplicateResultProcessor } from "./ReplicateResultProcessor";
export declare class ModuleReplicator extends AbstractModule {
_replicatorType?: RemoteType;
processor: ReplicateResultProcessor;
private _unresolvedErrorManager;
clearErrors(): void;
private _everyOnloadAfterLoadSettings;
_onReplicatorInitialised(): Promise<boolean>;
_everyOnDatabaseInitialized(showNotice: boolean): Promise<boolean>;
_everyBeforeReplicate(showMessage: boolean): Promise<boolean>;
/**
* obsolete method. No longer maintained and will be removed in the future.
* @deprecated v0.24.17
* @param showMessage If true, show message to the user.
*/
cleaned(showMessage: boolean): Promise<void>;
private onReplicationFailed;
_parseReplicationResult(docs: Array<PouchDB.Core.ExistingDocument<EntryDoc>>): Promise<boolean>;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -1,11 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type RemoteDBSettings } from "@lib/common/types";
import type { LiveSyncAbstractReplicator } from "@lib/replication/LiveSyncAbstractReplicator";
import { AbstractModule } from "@/modules/AbstractModule";
import type { LiveSyncCore } from "@/main";
export declare class ModuleReplicatorCouchDB extends AbstractModule {
_anyNewReplicator(settingOverride?: Partial<RemoteDBSettings>): Promise<LiveSyncAbstractReplicator | false>;
_everyAfterResumeProcess(): Promise<boolean>;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -1,10 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type RemoteDBSettings } from "@lib/common/types";
import type { LiveSyncAbstractReplicator } from "@lib/replication/LiveSyncAbstractReplicator";
import type { LiveSyncCore } from "@/main";
import { AbstractModule } from "@/modules/AbstractModule";
export declare class ModuleReplicatorMinIO extends AbstractModule {
_anyNewReplicator(settingOverride?: Partial<RemoteDBSettings>): Promise<LiveSyncAbstractReplicator | false>;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -1,116 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type AnyEntry, type EntryDoc, type LoadedEntry, type MetaEntry } from "@lib/common/types";
import type { ModuleReplicator } from "./ModuleReplicator";
import type { ReactiveSource } from "octagonal-wheels/dataobject/reactive_v2";
import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore";
export declare class ReplicateResultProcessor {
private log;
private logError;
private replicator;
constructor(replicator: ModuleReplicator);
get localDatabase(): import("../../lib/src/pouchdb/LiveSyncLocalDB").LiveSyncLocalDB;
get services(): import("../../lib/src/services/InjectableServices").InjectableServiceHub<import("../../lib/src/services/base/ServiceBase").ServiceContext>;
get core(): LiveSyncBaseCore;
getPath(entry: AnyEntry): string;
suspend(): void;
resume(): void;
private _suspended;
get isSuspended(): boolean;
/**
* Take a snapshot of the current processing state.
* This snapshot is stored in the KV database for recovery on restart.
*/
protected _takeSnapshot(): Promise<void>;
/**
* Trigger taking a snapshot.
*/
protected _triggerTakeSnapshot(): void;
/**
* Throttled version of triggerTakeSnapshot.
*/
protected triggerTakeSnapshot: import("octagonal-wheels/function").ThrottledFunction<() => void>;
/**
* Restore from snapshot.
*/
restoreFromSnapshot(): Promise<void>;
private _restoreFromSnapshot;
/**
* Restore from snapshot only once.
* @returns Promise that resolves when restoration is complete.
*/
restoreFromSnapshotOnce(): Promise<void>;
/**
* Perform the given procedure while counting the concurrency.
* @param proc async procedure to perform
* @param countValue reactive source to count concurrency
* @returns result of the procedure
*/
withCounting<T>(proc: () => Promise<T>, countValue: ReactiveSource<number>): Promise<T>;
/**
* Report the current status.
*/
protected reportStatus(): void;
/**
* Enqueue all the given changes for processing.
* @param changes Changes to enqueue
*/
enqueueAll(changes: PouchDB.Core.ExistingDocument<EntryDoc>[]): void;
/**
* Process the change if it is not a document change.
* @param change Change to process
* @returns True if the change was processed; false otherwise
*/
protected processIfNonDocumentChange(change: PouchDB.Core.ExistingDocument<EntryDoc>): boolean;
/**
* Queue of changes to be processed.
*/
private _queuedChanges;
/**
* List of changes being processed.
*/
private _processingChanges;
/**
* Enqueue the given document change for processing.
* @param doc Document change to enqueue
* @returns
*/
protected enqueueChange(doc: PouchDB.Core.ExistingDocument<EntryDoc>): void;
/**
* Trigger processing of the queued changes.
*/
protected triggerProcessQueue(): void;
/**
* Semaphore to limit concurrent processing.
* This is the per-id semaphore + concurrency-control (max 10 concurrent = 10 documents being processed at the same time).
*/
private _semaphore;
/**
* Flag indicating whether the process queue is currently running.
*/
private _isRunningProcessQueue;
/**
* Process the queued changes.
*/
private runProcessQueue;
/**
* Parse the given document change.
* @param change
* @returns
*/
parseDocumentChange(change: PouchDB.Core.ExistingDocument<EntryDoc>): Promise<void>;
protected applyToDatabase(doc: PouchDB.Core.ExistingDocument<AnyEntry>): Promise<void>;
private _applyToDatabase;
/**
* Phase 3: Apply the given entry to storage.
* @param entry
* @returns
*/
protected applyToStorage(entry: MetaEntry): Promise<void>;
/**
* Check whether processing is required for the given document.
* @param dbDoc Document to check
* @returns True if processing is required; false otherwise
*/
protected checkIsChangeRequiredForDatabaseProcessing(dbDoc: LoadedEntry): Promise<boolean>;
}

View File

@@ -1,15 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { AbstractModule } from "@/modules/AbstractModule.ts";
import { type FilePathWithPrefix } from "@lib/common/types";
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
import type { InjectableServiceHub } from "@lib/services/InjectableServices.ts";
import type { LiveSyncCore } from "@/main.ts";
export declare class ModuleConflictChecker extends AbstractModule {
_queueConflictCheckIfOpen(file: FilePathWithPrefix): Promise<void>;
_queueConflictCheck(file: FilePathWithPrefix): Promise<void>;
_waitForAllConflictProcessed(): Promise<boolean>;
conflictResolveQueue: QueueProcessor<FilePathWithPrefix, unknown>;
conflictCheckQueue: QueueProcessor<FilePathWithPrefix, FilePathWithPrefix>;
onBindFunction(core: LiveSyncCore, services: InjectableServiceHub): void;
}

View File

@@ -1,19 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { AbstractModule } from "@/modules/AbstractModule.ts";
import { type diff_check_result, type FilePathWithPrefix } from "@lib/common/types";
import type { InjectableServiceHub } from "@lib/services/InjectableServices.ts";
import type { LiveSyncCore } from "@/main.ts";
declare global {
interface LSEvents {
"conflict-cancelled": FilePathWithPrefix;
}
}
export declare class ModuleConflictResolver extends AbstractModule {
private _resolveConflictByDeletingRev;
checkConflictAndPerformAutoMerge(path: FilePathWithPrefix): Promise<diff_check_result>;
private _resolveConflict;
private _anyResolveConflictByNewest;
private _resolveAllConflictedFilesByNewerOnes;
onBindFunction(core: LiveSyncCore, services: InjectableServiceHub): void;
}

View File

@@ -1,36 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type TweakValues, type ObsidianLiveSyncSettings, type RemoteDBSettings } from "@lib/common/types.ts";
import { AbstractModule } from "@/modules/AbstractModule.ts";
import type { InjectableServiceHub } from "@lib/services/InjectableServices.ts";
import type { LiveSyncCore } from "@/main.ts";
export declare class ModuleResolvingMismatchedTweaks extends AbstractModule {
private _hasNotifiedAutoAcceptCompatibleUndefined;
private _collectMismatchedTweakKeys;
private _selectNewerTweakSide;
private _shouldAutoAcceptCompatibleLossy;
/**
* Hook before saving settings, to check if there are changes in tweak values, and if so,
* update the tweakModified timestamp to current time.
* This allows other devices to know that the tweak values have been changed and decide whether to accept the new values based on the modification time.
* @param next
* @param previous
* @returns
*/
_onBeforeSaveSettingData(next: ObsidianLiveSyncSettings, previous: ObsidianLiveSyncSettings): Promise<{
tweakModified: number;
} | undefined>;
_anyAfterConnectCheckFailed(): Promise<boolean | "CHECKAGAIN" | undefined>;
_checkAndAskResolvingMismatchedTweaks(preferred: TweakValues): Promise<[TweakValues | boolean, boolean]>;
_askResolvingMismatchedTweaks(): Promise<"OK" | "CHECKAGAIN" | "IGNORE">;
_fetchRemotePreferredTweakValues(trialSetting: RemoteDBSettings): Promise<TweakValues | false>;
_checkAndAskUseRemoteConfiguration(trialSetting: RemoteDBSettings): Promise<{
result: false | TweakValues;
requireFetch: boolean;
}>;
_askUseRemoteConfiguration(trialSetting: RemoteDBSettings, preferred: TweakValues): Promise<{
result: false | TweakValues;
requireFetch: boolean;
}>;
onBindFunction(core: LiveSyncCore, services: InjectableServiceHub): void;
}

View File

@@ -1,8 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LiveSyncCore } from "@/main";
import { AbstractModule } from "@/modules/AbstractModule";
export declare class ModuleBasicMenu extends AbstractModule {
_everyOnloadStart(): Promise<boolean>;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -1,15 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { AbstractModule } from "@/modules/AbstractModule.ts";
import type { LiveSyncCore } from "@/main.ts";
export declare class ModuleMigration extends AbstractModule {
migrateUsingDoctor(skipRebuild?: boolean, activateReason?: string, forceRescan?: boolean): Promise<boolean>;
migrateDisableBulkSend(): Promise<void>;
initialMessage(): Promise<boolean>;
askAgainForSetupURI(): Promise<boolean>;
hasIncompleteDocs(force?: boolean): Promise<boolean>;
hasCompromisedChunks(): Promise<boolean>;
_everyOnFirstInitialize(): Promise<boolean>;
_everyOnLayoutReady(): Promise<boolean>;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -1,28 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
import type { TFile } from "@/deps.ts";
import { type ReactiveSource } from "octagonal-wheels/dataobject/reactive";
import type { LiveSyncCore } from "@/main.ts";
export declare class ModuleObsidianEvents extends AbstractObsidianModule {
_everyOnloadStart(): Promise<boolean>;
__performAppReload(): void;
initialCallback: (() => void) | undefined;
swapSaveCommand(): void;
registerWatchEvents(): void;
hasFocus: boolean;
isLastHidden: boolean;
setHasFocus(hasFocus: boolean): void;
watchWindowVisibility(): void;
watchOnline(): void;
watchOnlineAsync(): Promise<void>;
watchWindowVisibilityAsync(): Promise<void>;
watchWorkspaceOpen(file: TFile | null): void;
watchWorkspaceOpenAsync(file: TFile): Promise<void>;
_everyOnLayoutReady(): Promise<boolean>;
private _askReload;
_totalProcessingCount?: ReactiveSource<number>;
private _scheduleAppReload;
_isReloadingScheduled(): boolean;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -1,8 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LiveSyncCore } from "@/main.ts";
import { AbstractModule } from "@/modules/AbstractModule.ts";
export declare class ModuleObsidianMenu extends AbstractModule {
_everyOnloadStart(): Promise<boolean>;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -0,0 +1,3 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
export type { ModuleDev } from "../../serviceFeatures/devFeature/types.ts";

View File

@@ -0,0 +1,26 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { ItemView, WorkspaceLeaf } from "@/deps.ts";
import TestPaneComponent from "./TestPane.svelte";
import type ObsidianLiveSyncPlugin from "@/main.ts";
import type { ModuleDev } from "@/modules/extras/ModuleDev.ts";
export declare const VIEW_TYPE_TEST = "ols-pane-test";
declare global {
interface LSEvents {
"debug-sync-status": string[];
}
}
export declare class TestPaneView extends ItemView {
component?: TestPaneComponent;
plugin: ObsidianLiveSyncPlugin;
moduleDev: ModuleDev;
icon: string;
title: string;
navigation: boolean;
getIcon(): string;
constructor(leaf: WorkspaceLeaf, plugin: ObsidianLiveSyncPlugin, moduleDev: ModuleDev);
getViewType(): string;
getDisplayText(): string;
onOpen(): Promise<void>;
onClose(): Promise<void>;
}

View File

@@ -1,8 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
export declare class ModuleObsidianGlobalHistory extends AbstractObsidianModule {
_everyOnloadStart(): Promise<boolean>;
showGlobalHistory(): void;
onBindFunction(core: typeof this.core, services: typeof core.services): void;
}

View File

@@ -1,13 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type FilePathWithPrefix, type diff_result } from "@lib/common/types.ts";
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
import type { LiveSyncCore } from "@/main.ts";
export declare class ModuleInteractiveConflictResolver extends AbstractObsidianModule {
_everyOnloadStart(): Promise<boolean>;
_anyResolveConflictByUI(filename: FilePathWithPrefix, conflictCheckResult: diff_result): Promise<boolean>;
allConflictCheck(): Promise<void>;
pickFileForResolve(): Promise<boolean>;
_allScanStat(): Promise<boolean>;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -1,11 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type TFile } from "@/deps.ts";
import type { FilePathWithPrefix, DocumentID } from "@lib/common/types.ts";
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
export declare class ModuleObsidianDocumentHistory extends AbstractObsidianModule {
_everyOnloadStart(): Promise<boolean>;
showHistory(file: TFile | FilePathWithPrefix, id?: DocumentID): void;
fileHistory(): Promise<void>;
onBindFunction(core: typeof this.core, services: typeof core.services): void;
}

View File

@@ -1,24 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type ObsidianLiveSyncSettings } from "@lib/common/types";
import { AbstractModule } from "@/modules/AbstractModule.ts";
import type { ServiceContext } from "@lib/services/base/ServiceBase.ts";
import type { InjectableServiceHub } from "@lib/services/InjectableServices.ts";
import type { LiveSyncCore } from "@/main.ts";
export declare class ModuleObsidianSettingsAsMarkdown extends AbstractModule {
_everyOnloadStart(): Promise<boolean>;
extractSettingFromWholeText(data: string): {
preamble: string;
body: string;
postscript: string;
};
parseSettingFromMarkdown(filename: string, data?: string): Promise<{
preamble: string;
body: string;
postscript: string;
}>;
checkAndApplySettingFromMarkdown(filename: string, automated?: boolean): Promise<void>;
generateSettingForMarkdown(settings?: ObsidianLiveSyncSettings, keepCredential?: boolean): Partial<ObsidianLiveSyncSettings>;
saveSettingToMarkdown(filename: string): Promise<void>;
onBindFunction(core: LiveSyncCore, services: InjectableServiceHub<ServiceContext>): void;
}

View File

@@ -1,12 +0,0 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { ObsidianLiveSyncSettingTab } from "./SettingDialogue/ObsidianLiveSyncSettingTab.ts";
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
import type { LiveSyncCore } from "@/main.ts";
export declare class ModuleObsidianSettingDialogue extends AbstractObsidianModule {
settingTab: ObsidianLiveSyncSettingTab;
_everyOnloadStart(): Promise<boolean>;
openSetting(): void;
get appId(): string;
onBindFunction(core: LiveSyncCore, services: typeof core.services): void;
}

View File

@@ -1,121 +1,3 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type ObsidianLiveSyncSettings } from "@lib/common/types.ts";
import { AbstractModule } from "@/modules/AbstractModule.ts";
/**
* User modes for onboarding and setup
*/
export declare const enum UserMode {
/**
* New User Mode - for users who are new to the plugin
*/
NewUser = "new-user",
/**
* Existing User Mode - for users who have used the plugin before, or just configuring again
*/
ExistingUser = "existing-user",
/**
* Unknown User Mode - for cases where the user mode is not determined
*/
Unknown = "unknown",
/**
* Update User Mode - for users who are updating configuration. May be `existing-user` as well, but possibly they want to treat it differently.
*/
Update = "unknown" // eslint-disable-line @typescript-eslint/no-duplicate-enum-values -- Duplicate enum value
}
/**
* Setup Manager to handle onboarding and configuration setup
*/
export declare class SetupManager extends AbstractModule {
get dialogManager(): import("../../lib/src/UI/svelteDialog.ts").SvelteDialogManagerBase<import("../../lib/src/services/base/ServiceBase.ts").ServiceContext>;
/**
* Starts the onboarding process
* @returns Promise that resolves to true if onboarding completed successfully, false otherwise
*/
startOnBoarding(): Promise<boolean>;
/**
* Handles the onboarding process based on user mode
* @param userMode
* @returns Promise that resolves to true if onboarding completed successfully, false otherwise
*/
onOnboard(userMode: UserMode): Promise<boolean>;
/**
* Handles setup using a setup URI
* @param userMode
* @param setupURI
* @returns Promise that resolves to true if onboarding completed successfully, false otherwise
*/
onUseSetupURI(userMode: UserMode, setupURI?: string): Promise<boolean>;
/**
* Handles manual setup for CouchDB
* @param userMode
* @param currentSetting
* @param activate Whether to activate the CouchDB as remote type
* @returns Promise that resolves to true if setup completed successfully, false otherwise
*/
onCouchDBManualSetup(userMode: UserMode, currentSetting: ObsidianLiveSyncSettings, activate?: boolean): Promise<boolean>;
/**
* Handles manual setup for S3-compatible bucket
* @param userMode
* @param currentSetting
* @param activate Whether to activate the Bucket as remote type
* @returns Promise that resolves to true if setup completed successfully, false otherwise
*/
onBucketManualSetup(userMode: UserMode, currentSetting: ObsidianLiveSyncSettings, activate?: boolean): Promise<boolean>;
/**
* Handles manual setup for P2P
* @param userMode
* @param currentSetting
* @param activate Whether to activate the P2P as remote type (as P2P Only setup)
* @returns Promise that resolves to true if setup completed successfully, false otherwise
*/
onP2PManualSetup(userMode: UserMode, currentSetting: ObsidianLiveSyncSettings, activate?: boolean): Promise<boolean>;
/**
* Handles only E2EE configuration
* @param userMode
* @param currentSetting
* @returns
*/
onlyE2EEConfiguration(userMode: UserMode, currentSetting: ObsidianLiveSyncSettings): Promise<boolean>;
/**
* Handles manual configuration flow (E2EE + select server)
* @param originalSetting
* @param userMode
* @returns
*/
onConfigureManually(originalSetting: ObsidianLiveSyncSettings, userMode: UserMode): Promise<boolean>;
/**
* Handles server selection during manual configuration
* @param currentSetting
* @param userMode
* @returns
*/
onSelectServer(currentSetting: ObsidianLiveSyncSettings, userMode: UserMode): Promise<boolean>;
/**
* Confirms and applies settings obtained from the wizard
* @param newConf
* @param _userMode
* @param activate Whether to activate the remote type in the new settings
* @param extra Extra function to run before applying settings
* @returns Promise that resolves to true if settings applied successfully, false otherwise
*/
onConfirmApplySettingsFromWizard(newConf: ObsidianLiveSyncSettings, _userMode: UserMode, activate?: boolean, extra?: () => void): Promise<boolean>;
/**
* Prompts the user with QR code scanning instructions
* @returns Promise that resolves to false as QR code instruction dialog does not yield settings directly
*/
onPromptQRCodeInstruction(): Promise<boolean>;
/**
* Decodes settings from a QR code string and applies them
* @param qr QR code string containing encoded settings
* @returns Promise that resolves to true if settings applied successfully, false otherwise
*/
decodeQR(qr: string): Promise<boolean>;
/**
* Applies the new settings to the core settings and saves them
* @param newConf
* @param userMode
* @returns Promise that resolves to true if settings applied successfully, false otherwise
*/
applySetting(newConf: ObsidianLiveSyncSettings, userMode: UserMode): Promise<boolean>;
}
export { UserMode, getSetupManager, type SetupManagerAPI as SetupManager, } from "@/serviceFeatures/setupManager/index.ts";

View File

@@ -0,0 +1,12 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { ConfigSyncHost } from "./types.ts";
/**
* Registers commands, ribbon icons, and custom SVG icons for configuration synchronisation.
*
* @param host - The service feature host.
* @param handlers - Action triggers.
*/
export declare function registerConfigSyncCommands(host: ConfigSyncHost, handlers: {
showPluginSyncModal: () => void;
}): void;

View File

@@ -0,0 +1,27 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils";
import type { FilePath } from "@lib/common/types.ts";
import type { ConfigSyncHost } from "./types.ts";
import type { ConfigSyncState } from "./state.ts";
/**
* Binds all required events for configuration synchronisation onto the application lifecycle and replicator.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param handlers - Event response triggers.
*/
export declare function bindConfigSyncEvents(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, handlers: {
showPluginSyncModal: () => void;
watchVaultRawEventsAsync: (path: FilePath) => Promise<boolean>;
}): void;
/**
* Configures the customisation synchronisation status.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param mode - The sync activation mode option.
*/
export declare function configureHiddenFileSync(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, mode: "DISABLE" | "CUSTOMIZE" | "DISABLE_CUSTOM"): Promise<void>;

View File

@@ -0,0 +1,8 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { ConfigSyncServices, ConfigSyncModules } from "./types.ts";
/**
* A service feature hook that initialises and manages the configuration synchronisation module.
* This sets up the scanning processors, watches for local/remote config changes, and binds UI dialogues.
*/
export declare const useConfigSync: import("@/types.ts").ObsidianServiceFeatureFunction<ConfigSyncServices, ConfigSyncModules, "plugin" | "app" | "liveSyncPlugin", void>;

View File

@@ -0,0 +1,128 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils";
import type { FilePath, FilePathWithPrefix, LoadedEntry, AnyEntry } from "@lib/common/types.ts";
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
import type { ConfigSyncHost, IPluginDataExDisplay, PluginDataExDisplay, LoadedEntryPluginDataExFile, PluginDataExFile } from "./types.ts";
import type { ConfigSyncState } from "./state.ts";
/**
* Class representing plugin configuration metadata and display structures for V2 synchronisation.
*/
export declare class PluginDataExDisplayV2 {
documentPath: FilePathWithPrefix;
category: string;
term: string;
files: LoadedEntryPluginDataExFile[];
name: string;
confKey: string;
constructor(data: IPluginDataExDisplay);
setFile(file: LoadedEntryPluginDataExFile): Promise<void>;
deleteFile(filename: string): void;
_displayName: string | undefined;
_version: string | undefined;
applyLoadedManifest(): void;
get displayName(): string;
get version(): string | undefined;
get mtime(): number;
}
/**
* Reloads the plugin list by clearing the cache and executing updates.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param showMessage - Whether to display progress messages.
*/
export declare function reloadPluginList(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, showMessage: boolean): Promise<void>;
/**
* Loads plugin configuration data from the database.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param path - The database document path.
* @returns Deserialised plugin display details, or false if not found.
*/
export declare function loadPluginData(host: ConfigSyncHost, log: LogFunction, path: FilePathWithPrefix): Promise<PluginDataExDisplay | false>;
/**
* Creates a V2 plugin metadata descriptor from the unified path.
*
* @param host - The service feature host.
* @param unifiedPathV2 - V2 unified path database key.
* @returns Initialised plugin display descriptor.
*/
export declare function createPluginDataFromV2(host: ConfigSyncHost, unifiedPathV2: FilePathWithPrefix): PluginDataExDisplayV2 | undefined;
/**
* Creates a file entry structure from a V2 unified database document.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param unifiedPathV2 - V2 unified path database key.
* @param loaded - Pre-fetched database document, if available.
* @returns The V2 file descriptor.
*/
export declare function createPluginDataExFileV2(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, unifiedPathV2: FilePathWithPrefix, loaded?: LoadedEntry): Promise<false | LoadedEntryPluginDataExFile>;
/**
* Updates the plugin display list for a V2 unified document path.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param showMessage - Whether to show notifications.
* @param unifiedFilenameWithKey - Unified database document path.
*/
export declare function updatePluginListV2(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, showMessage: boolean, unifiedFilenameWithKey: FilePathWithPrefix): Promise<void>;
/**
* Scans the database and updates the active configuration items list.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param showMessage - Whether to show progress messages.
* @param updatedDocumentPath - Optional target document path to narrow update.
*/
export declare function updatePluginList(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, showMessage: boolean, updatedDocumentPath?: FilePathWithPrefix): Promise<void>;
/**
* Migrates configuration sync structure V1 (single monolithic metadata doc) to V2 (split documents).
*
* @param host - The service feature host.
* @param log - The logging function.
* @param showMessage - Whether to show progress logs in UI.
* @param entry - The database entry to migrate.
*/
export declare function migrateV1ToV2(host: ConfigSyncHost, log: LogFunction, showMessage: boolean, entry: AnyEntry): Promise<void>;
/**
* Helper to recursively list files in Obsidian storage up to a given depth.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param path - The folder path.
* @param lastDepth - Remaining depth levels to traverse.
* @returns Array of file paths found.
*/
export declare function getFiles(host: ConfigSyncHost, log: LogFunction, path: string, lastDepth: number): Promise<string[]>;
/**
* Scans internal configuration files in Obsidian storage config folder.
*
* @param host - The service feature host.
* @param log - The logging function.
* @returns Array of configuration file paths.
*/
export declare function scanInternalFiles(host: ConfigSyncHost, log: LogFunction): Promise<FilePath[]>;
/**
* Creates a file details entry from a local storage file.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param path - Local file path.
* @returns File descriptor details, or false if stat fails.
*/
export declare function makeEntryFromFile(host: ConfigSyncHost, log: LogFunction, path: FilePath): Promise<false | PluginDataExFile>;
/**
* Creates a QueueProcessor for scanning V1 plugins.
*/
export declare function createPluginScanProcessor(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState): QueueProcessor<AnyEntry, never>;
/**
* Creates a QueueProcessor for scanning V2 plugins.
*/
export declare function createPluginScanProcessorV2(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState): QueueProcessor<AnyEntry, never>;

View File

@@ -0,0 +1,30 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { PeriodicProcessor } from "@/common/PeriodicProcessor.ts";
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
import type { PluginDialogModal } from "@/features/ConfigSync/PluginDialogModal.ts";
import type { IPluginDataExDisplay } from "./types.ts";
/**
* Represents the runtime state of the configuration synchronisation feature.
* This state is scoped to the feature lifecycle, containing active processors,
* cached metadata, and UI dialogues.
*/
export interface ConfigSyncState {
pluginList: IPluginDataExDisplay[];
pluginDialog: PluginDialogModal | undefined;
periodicPluginSweepProcessor: PeriodicProcessor | undefined;
conflictResolutionProcessor: QueueProcessor<any, any> | undefined; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration
loadedManifest_mTime: Map<string, number>;
updatingV2Count: number;
updatePluginListV2Task: (() => void) | undefined;
pluginScanProcessor: QueueProcessor<any, any> | undefined; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration
pluginScanProcessorV2: QueueProcessor<any, any> | undefined; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration
recentProcessedInternalFiles: string[];
}
/**
* Creates and initialises a new configuration synchronisation state object
* with default values.
*
* @returns A freshly initialised {@link ConfigSyncState} object.
*/
export declare function createConfigSyncState(): ConfigSyncState;

View File

@@ -0,0 +1,32 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { PluginManifest } from "@/deps.ts";
import type { PluginDataExDisplay } from "./types.ts";
/**
* A Svelte store holding the list of plug-ins and their synchronisation details for UI display.
*/
export declare const pluginList: import("svelte/store").Writable<PluginDataExDisplay[]>;
/**
* A Svelte store indicating whether the plug-in enumeration process is currently running.
*/
export declare const pluginIsEnumerating: import("svelte/store").Writable<boolean>;
/**
* A Svelte store representing the progress of version 2 plug-in synchronisation (from 0 to 1).
*/
export declare const pluginV2Progress: import("svelte/store").Writable<number>;
/**
* A local map caching plug-in manifests by their identifier keys.
*/
export declare const pluginManifests: Map<string, PluginManifest>;
/**
* A Svelte store wrapper around {@link pluginManifests} to notify subscribers of updates.
*/
export declare const pluginManifestStore: import("svelte/store").Writable<Map<string, PluginManifest>>;
/**
* Updates a plug-in's manifest inside {@link pluginManifests} and notifies the store subscribers
* if the manifest has changed.
*
* @param key - The plug-in identifier key.
* @param manifest - The new plug-in manifest data.
*/
export declare function setManifest(key: string, manifest: PluginManifest): void;

View File

@@ -0,0 +1,111 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils";
import type { FilePath, FilePathWithPrefix } from "@lib/common/types.ts";
import type { ConfigSyncHost, IPluginDataExDisplay, PluginDataEx } from "./types.ts";
import type { ConfigSyncState } from "./state.ts";
import { PluginDataExDisplayV2 } from "./pluginScanner.ts";
/**
* Checks whether the configuration synchronisation module is enabled in settings.
*
* @param host - The service feature host.
* @returns True if enabled, false otherwise.
*/
export declare function isThisModuleEnabled(host: ConfigSyncHost): boolean;
/**
* Compares two plugin data sets by displaying a resolve modal dialog.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param dataA - Left hand configuration item.
* @param dataB - Right hand configuration item.
* @param compareEach - Whether to compare file by file.
* @returns Promise resolving to true if applied successfully, false otherwise.
*/
export declare function compareUsingDisplayData(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, dataA: IPluginDataExDisplay, dataB: IPluginDataExDisplay, compareEach?: boolean): Promise<boolean>;
/**
* Applies customization data for V2 split files.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param data - The plugin V2 display model.
* @param content - Optional specific file content override.
* @returns True if applied successfully, false otherwise.
*/
export declare function applyDataV2(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, data: PluginDataExDisplayV2, content?: string): Promise<boolean>;
/**
* Applies configuration data to local storage and updates active systems.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param data - The configuration display description.
* @param content - Optional merged file content.
* @returns True if successful, false otherwise.
*/
export declare function applyData(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, data: IPluginDataExDisplay, content?: string): Promise<boolean>;
/**
* Deletes configuration documents from the database and runs status updates.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param data - The target plugin configurations to clean up.
* @returns True if successful, false otherwise.
*/
export declare function deleteData(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, data: PluginDataEx): Promise<boolean>;
/**
* Stores a customization file in V2 database split format.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param path - Local file path.
* @param term - Local terminal name.
* @param force - True to bypass change verification checks.
* @returns Database operation response structure.
*/
export declare function storeCustomisationFileV2(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, path: FilePath, term: string, force?: boolean): Promise<any>; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration
/**
* Stores local customization files to database records.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param path - Local file path.
* @param termOverRide - Device identifier override.
* @returns DB operation response.
*/
export declare function storeCustomizationFiles(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, path: FilePath, termOverRide?: string): Promise<any>; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration
/**
* Marks config file deleted in the database.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param prefixedFileName - Unified db file path.
* @param forceWrite - Force deletion write operation.
* @returns True if successfully marked deleted, false otherwise.
*/
export declare function deleteConfigOnDatabase(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, prefixedFileName: FilePathWithPrefix, forceWrite?: boolean): Promise<boolean>;
/**
* Scans all customization config files, comparing local and DB databases.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param showMessage - True to print progress messages.
*/
export declare function scanAllConfigFiles(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, showMessage: boolean): Promise<void>;
/**
* Monitors and processes Obsidian storage raw file events for synchronisation.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The configuration sync state.
* @param path - The modified file path.
* @returns True if processed, false otherwise.
*/
export declare function watchVaultRawEventsAsync(host: ConfigSyncHost, log: LogFunction, state: ConfigSyncState, path: FilePath): Promise<boolean>;

View File

@@ -0,0 +1,71 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
import type { FilePathWithPrefix, LoadedEntry } from "@lib/common/types.ts";
/**
* A union of service keys required by the configuration synchronisation feature.
*/
export type ConfigSyncServices = "API" | "appLifecycle" | "setting" | "vault" | "path" | "database" | "databaseEvents" | "fileProcessing" | "keyValueDB" | "replication" | "conflict" | "control";
/**
* A union of service module keys required by the configuration synchronisation feature.
*/
export type ConfigSyncModules = "storageAccess" | "fileHandler";
/**
* The host type representing the injected service container with configuration synchronisation capabilities.
*/
export type ConfigSyncHost = NecessaryObsidianServices<ConfigSyncServices, ConfigSyncModules, "app" | "plugin">;
/**
* Represents metadata and content structure of an individual file within a plug-in.
*/
export type PluginDataExFile = {
filename: string;
data: string[];
mtime: number;
size: number;
version?: string;
hash?: string;
displayName?: string;
};
/**
* Defines the display properties and structure for a plug-in sync entry used in UI dialogues.
*/
export interface IPluginDataExDisplay {
documentPath: FilePathWithPrefix;
category: string;
name: string;
term: string;
displayName?: string;
files: (LoadedEntryPluginDataExFile | PluginDataExFile)[];
version?: string;
mtime: number;
}
/**
* Represents the display model of a plug-in, including its category, file list, and modification time.
*/
export type PluginDataExDisplay = {
documentPath: FilePathWithPrefix;
category: string;
name: string;
term: string;
displayName?: string;
files: PluginDataExFile[];
version?: string;
mtime: number;
};
/**
* Combines a database loaded entry with plug-in specific file metadata.
*/
export type LoadedEntryPluginDataExFile = LoadedEntry & PluginDataExFile;
/**
* Represents a plug-in's synchronisation schema payload stored in the database.
*/
export type PluginDataEx = {
documentPath?: FilePathWithPrefix;
category: string;
name: string;
displayName?: string;
term: string;
files: PluginDataExFile[];
version?: string;
mtime: number;
};

View File

@@ -0,0 +1,130 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { FilePathWithPrefix } from "@lib/common/types.ts";
import type { PluginDataEx } from "./types.ts";
/**
* A zero-width space character used as a field delimiter in the custom serialisation format.
*/
export declare const d = "\u200B";
/**
* A newline character used as a record delimiter in the custom serialisation format.
*/
export declare const d2 = "\n";
/**
* Serialises a plugin data structure into a custom compact string format.
*
* @param data - The plugin data to serialise.
* @returns The serialised compact string.
*/
export declare function serialize(data: PluginDataEx): string;
/**
* A placeholder header string used to represent the start of the serialised configuration chunk stream.
*/
export declare const DUMMY_HEAD: string;
/**
* A placeholder footer string used to represent the end of the serialised configuration chunk stream.
*/
export declare const DUMMY_END: string;
/**
* Splits source strings by compact format delimiters.
*
* @param sources - The source strings to split.
* @returns Split string array.
*/
export declare function splitWithDelimiters(sources: string[]): string[];
/**
* Creates a tokenizer helper for deserialisation parsing.
*
* @param source - Split string token sources.
* @returns Tokenizer helper object.
*/
export declare function getTokenizer(source: string[]): {
next(): string;
nextLine(): void;
};
/**
* Deserialises tokenised array lines into a plugin data structure.
*
* @param str - The array lines to deserialise.
* @returns Deserialised plugin data.
*/
export declare function deserialize2(str: string[]): PluginDataEx;
/**
* Deserialises file content string arrays into a target object representation.
* Supports compact prefix format, JSON parsing, and YAML fallback.
*
* @param str - Content string lines.
* @param def - Fallback default value.
* @returns Deserialised object structure.
*/
export declare function deserialize<T>(str: string[], def: T): any; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration
/**
* Maps a configuration category and base path to a vault relative subdirectory.
*
* @param category - Configuration category.
* @param configDir - The main system configuration directory path.
* @returns Vault folder suffix path.
*/
export declare function categoryToFolder(category: string, configDir?: string): string;
/**
* Resolves local file category based on the system configuration directory.
*
* @param filePath - Local file path.
* @param configDir - Vault system config folder name.
* @param useV2 - Whether V2 plugin structure is active.
* @param useSyncPluginEtc - Whether custom subfolders under plugins are synchronised.
* @returns Category identifier.
*/
export declare function getFileCategory(filePath: string, configDir: string, useV2: boolean, useSyncPluginEtc: boolean): "CONFIG" | "THEME" | "SNIPPET" | "PLUGIN_MAIN" | "PLUGIN_ETC" | "PLUGIN_DATA" | "";
/**
* Checks if the file path is a valid customization sync path candidate.
*
* @param filePath - Target file path.
* @param configDir - Vault configuration folder path.
* @param useV2 - Whether V2 sync is enabled.
* @param useSyncPluginEtc - Whether config files sync is enabled.
* @returns True if path is a sync target.
*/
export declare function isTargetPath(filePath: string, configDir: string, useV2: boolean, useSyncPluginEtc: boolean): boolean;
/**
* Converts local path into unified database document path.
*
* @param path - Local file path.
* @param term - Active device name.
* @param configDir - Vault config directory name.
* @param useV2 - Whether V2 is active.
* @param useSyncPluginEtc - Whether sync plugin etc is active.
* @returns The database path identifier.
*/
export declare function filenameToUnifiedKey(path: string, term: string, configDir: string, useV2: boolean, useSyncPluginEtc: boolean): FilePathWithPrefix;
/**
* Converts local path into V2 unified database document path.
*
* @param path - Local file path.
* @param term - Active device name.
* @param configDir - Vault config directory name.
* @param useV2 - Whether V2 is active.
* @param useSyncPluginEtc - Whether sync plugin etc is active.
* @returns The database path identifier.
*/
export declare function filenameWithUnifiedKey(path: string, term: string, configDir: string, useV2: boolean, useSyncPluginEtc: boolean): FilePathWithPrefix;
/**
* Returns database prefix path filter for a terminal configuration.
*
* @param term - Active device name.
* @returns Database path prefix string.
*/
export declare function unifiedKeyPrefixOfTerminal(term: string): FilePathWithPrefix;
/**
* Parses a V2 unified database path into its constituent components.
*
* @param unifiedPath - Unified path metadata document identifier.
* @returns Parsed components.
*/
export declare function parseUnifiedPath(unifiedPath: FilePathWithPrefix): {
category: string;
device: string;
key: string;
filename: string;
pathV1: FilePathWithPrefix;
};

View File

@@ -0,0 +1,12 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type FilePathWithPrefix } from "@lib/common/types";
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
import type { NecessaryObsidianFeature } from "@/types";
export type ConflictCheckerHost = NecessaryObsidianFeature<"API" | "conflict" | "vault" | "setting">;
export declare const queueConflictCheckIfOpenHandler: (host: ConflictCheckerHost, file: FilePathWithPrefix) => Promise<void>;
export declare const queueConflictCheckHandler: (host: ConflictCheckerHost, queue: QueueProcessor<FilePathWithPrefix, any>, file: FilePathWithPrefix) => Promise<void>; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration
export declare function useConflictChecker(host: ConflictCheckerHost): {
conflictCheckQueue: QueueProcessor<FilePathWithPrefix, FilePathWithPrefix>;
conflictResolveQueue: QueueProcessor<FilePathWithPrefix, unknown>;
};

View File

@@ -0,0 +1,16 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { AUTO_MERGED, MISSING_OR_ERROR, type diff_check_result, type FilePathWithPrefix } from "@lib/common/types";
import type { NecessaryObsidianFeature } from "@/types";
declare global {
interface LSEvents {
"conflict-cancelled": FilePathWithPrefix;
}
}
export type ConflictResolverHost = NecessaryObsidianFeature<"API" | "conflict" | "appLifecycle" | "replication" | "vault" | "setting" | "database", "databaseFileAccess" | "fileHandler" | "storageAccess">;
export declare const resolveConflictByDeletingRevHandler: (host: ConflictResolverHost, path: FilePathWithPrefix, deleteRevision: string, subTitle?: string) => Promise<typeof MISSING_OR_ERROR | typeof AUTO_MERGED>;
export declare const checkConflictAndPerformAutoMerge: (host: ConflictResolverHost, path: FilePathWithPrefix) => Promise<diff_check_result>;
export declare const resolveConflictHandler: (host: ConflictResolverHost, filename: FilePathWithPrefix) => Promise<void>;
export declare const resolveConflictByNewestHandler: (host: ConflictResolverHost, filename: FilePathWithPrefix) => Promise<boolean>;
export declare const resolveAllConflictedFilesByNewerOnesHandler: (host: ConflictResolverHost) => Promise<void>;
export declare function useConflictResolver(host: ConflictResolverHost): void;

View File

@@ -0,0 +1,4 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
export { useConflictChecker } from "./conflictChecker";
export { useConflictResolver } from "./conflictResolver";

View File

@@ -0,0 +1,11 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { DatabaseMaintenanceHost } from "./types.ts";
/**
* Registers commands and event listeners for database maintenance capabilities.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function registerDatabaseMaintenanceCommands(host: DatabaseMaintenanceHost, log: LogFunction): void;

View File

@@ -0,0 +1,11 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { DatabaseMaintenanceHost } from "./types.ts";
/**
* Commands the remote CouchDB database to perform compaction and monitors its progress.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function compactDatabase(host: DatabaseMaintenanceHost, log: LogFunction): Promise<void>;

View File

@@ -0,0 +1,11 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { DatabaseMaintenanceHost } from "./types.ts";
/**
* Analyses the database and details chunk utilisation, copying a TSV summary to the clipboard.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function analyseDatabase(host: DatabaseMaintenanceHost, log: LogFunction): Promise<void>;

View File

@@ -0,0 +1,80 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type DocumentID } from "@lib/common/types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { DatabaseMaintenanceHost } from "./types.ts";
type ChunkID = DocumentID;
type NoteDocumentID = DocumentID;
type Rev = string;
type ChunkUsageMap = Map<NoteDocumentID, Map<Rev, Set<ChunkID>>>;
/**
* Resurrects deleted chunks that are still referenced and used by files in the database.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function resurrectChunks(host: DatabaseMaintenanceHost, log: LogFunction): Promise<void>;
/**
* Commits the deletion of files marked as deleted, removing them permanently from the database.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function commitFileDeletion(host: DatabaseMaintenanceHost, log: LogFunction): Promise<void>;
/**
* Permanently deletes chunks already marked as deleted.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function commitChunkDeletion(host: DatabaseMaintenanceHost, log: LogFunction): Promise<void>;
/**
* Marks chunks that are not referenced by any files in the database as deleted.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function markUnusedChunks(host: DatabaseMaintenanceHost, log: LogFunction): Promise<void>;
/**
* Directly removes unused chunks from the local database.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function removeUnusedChunks(host: DatabaseMaintenanceHost, log: LogFunction): Promise<void>;
/**
* Scans key-value store logs to calculate unused chunks.
*
* @param host - The service container host.
* @returns Scan summary.
*/
export declare function scanUnusedChunks(host: DatabaseMaintenanceHost): Promise<{
chunkSet: Set<DocumentID>;
chunkUsageMap: ChunkUsageMap;
unusedSet: Set<DocumentID>;
}>;
/**
* Tracks database changes to maintain the chunk usage map cache.
*
* @param host - The service container host.
* @param log - The logger function.
* @param fromStart - Whether to force scan from the beginning of sequence.
* @param showNotice - Whether to show log notices to user.
*/
export declare function trackChanges(host: DatabaseMaintenanceHost, log: LogFunction, fromStart?: boolean, showNotice?: boolean): Promise<void>;
/**
* Perfroms the legacy Garbage Collection process, scanning and removing unreferenced chunks.
*
* @param host - The service container host.
* @param log - The logger function.
* @param showingNotice - Whether to show log notices to user.
*/
export declare function performGC(host: DatabaseMaintenanceHost, log: LogFunction, showingNotice?: boolean): Promise<void>;
/**
* Runs Garbage Collection V3, which validates synchronization progress across connected nodes before deleting.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function gcv3(host: DatabaseMaintenanceHost, log: LogFunction): Promise<void>;
export {};

View File

@@ -0,0 +1,18 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { DatabaseMaintenanceServices } from "./types.ts";
/**
* A service feature hook that initialises and manages the database maintenance module.
* This registers maintenance commands and provides database compaction, diagnostic, and garbage collection utilities.
*/
export declare const useDatabaseMaintenance: import("@/types.ts").ObsidianServiceFeatureFunction<DatabaseMaintenanceServices, "storageAccess", "plugin", {
gcv3: () => Promise<void>;
analyseDatabase: () => Promise<void>;
compactDatabase: () => Promise<void>;
performGC: (showingNotice?: boolean) => Promise<void>;
resurrectChunks: () => Promise<void>;
commitFileDeletion: () => Promise<void>;
commitChunkDeletion: () => Promise<void>;
markUnusedChunks: () => Promise<void>;
removeUnusedChunks: () => Promise<void>;
}>;

View File

@@ -0,0 +1,15 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
/**
* A union of service keys required by the database maintenance feature.
*/
export type DatabaseMaintenanceServices = "API" | "setting" | "UI" | "database" | "keyValueDB" | "replication" | "replicator" | "vault";
/**
* A union of service module keys required by the database maintenance feature.
*/
export type DatabaseMaintenanceModules = "storageAccess";
/**
* The host type representing the injected service container with database maintenance capabilities.
*/
export type DatabaseMaintenanceHost = NecessaryObsidianServices<DatabaseMaintenanceServices, DatabaseMaintenanceModules, "plugin">;

View File

@@ -0,0 +1,49 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type LOG_LEVEL } from "@lib/common/types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { DatabaseMaintenanceHost } from "./types.ts";
/**
* Checks if garbage collection can be performed based on plug-in settings.
*
* @param host - The service container host.
* @param log - The logger function.
* @returns True if garbage collection is available, false otherwise.
*/
export declare function isGCAvailable(host: DatabaseMaintenanceHost, log: LogFunction): boolean;
/**
* Shows a confirmation dialogue to the user with customiseable options.
*
* @param host - The service container host.
* @param title - The title of the dialogue.
* @param message - The body message of the dialogue.
* @param affirmative - The positive confirmation label.
* @param negative - The negative cancellation label.
* @returns A promise resolving to true if approved, false otherwise.
*/
export declare function confirmDialogue(host: DatabaseMaintenanceHost, title: string, message: string, affirmative?: string, negative?: string): Promise<boolean>;
/**
* Retrieves all chunk information from the local database.
*
* @param host - The service container host.
* @param log - The logger function.
* @param includeDeleted - Whether to include deleted chunks in the scan.
* @returns A promise resolving to the retrieved chunk collections.
*/
export declare function retrieveAllChunks(host: DatabaseMaintenanceHost, log: LogFunction, includeDeleted?: boolean): Promise<{
used: Set<string>;
existing: Map<string, import("@lib/common/types.ts").EntryLeaf>;
}>;
/**
* Creates a progress bar tracker that logs lifecycle states.
*
* @param log - The logger function.
* @param prefix - A text prefix to prepend to all progress messages.
* @param level - The log level for progress updates.
* @returns An object to log, perform once-off updates, or finish the progress.
*/
export declare function createProgressBar(log: LogFunction, prefix?: string, level?: LOG_LEVEL): {
log: (msg: string) => void;
once: (msg: string) => void;
done: (msg?: string) => void;
};

View File

@@ -0,0 +1,37 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { DevFeatureHost } from "./types.ts";
import type { DevFeatureState } from "./state.ts";
import type { LogFunction } from "@lib/services/lib/logUtils";
/**
* Commits a log entry for missing translation keys inside local settings directory.
*
* @param host - The service feature host context.
* @param log - The logger function.
* @param key - The missing translation key.
*/
export declare function onMissingTranslation(host: DevFeatureHost, log: LogFunction, key: string): Promise<void>;
/**
* Automatically creates a conflicted revision for testing conflict resolution.
*
* @param host - The service feature host context.
*/
export declare function createConflict(host: DevFeatureHost): Promise<void>;
/**
* Appends a test result to the Svelte writable store.
*
* @param state - The active feature state.
* @param name - The test name or category.
* @param key - The unique test identifier.
* @param result - True if passed, false if failed.
* @param summary - Optional summary message.
* @param message - Optional detailed stacktrace or assertion info.
*/
export declare function addTestResult(state: DevFeatureState, name: string, key: string, result: boolean, summary?: string, message?: string): void;
/**
* Dumps information of the specified document for debugging purposes.
*
* @param host - The service feature host context.
* @param file - The file path to dump.
*/
export declare function dumpDocument(host: DevFeatureHost, file: string | undefined): void;

View File

@@ -0,0 +1,8 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { DevFeatureServices, DevFeatureModules } from "./types.ts";
/**
* A service feature hook that initialises dev/testing utilities.
* Handles missing translation captures, test panels, and debugging commands.
*/
export declare const useDevFeature: import("@/types.ts").ObsidianServiceFeatureFunction<DevFeatureServices, DevFeatureModules, "app" | "liveSyncPlugin", void>;

View File

@@ -0,0 +1,13 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type Writable } from "svelte/store";
/**
* Interface representing the state of the dev feature, including test results.
*/
export interface DevFeatureState {
testResults: Writable<[boolean, string, string][]>;
}
/**
* Creates the initial state object.
*/
export declare function createInitialState(): DevFeatureState;

View File

@@ -0,0 +1,22 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
import { type Writable } from "svelte/store";
/**
* Service keys required by the development utility feature.
*/
export type DevFeatureServices = "API" | "setting" | "appLifecycle" | "test" | "path" | "vault" | "keyValueDB" | "database" | "UI";
/**
* Service modules required by the development utility feature.
*/
export type DevFeatureModules = "storageAccess" | "databaseFileAccess";
/**
* The host type representing the injected service container with dev capabilities.
*/
export type DevFeatureHost = NecessaryObsidianServices<DevFeatureServices, DevFeatureModules, "app" | "liveSyncPlugin">;
/**
* Interface for the dev feature matching the shape expected by Svelte test panes.
*/
export interface ModuleDev {
testResults: Writable<[boolean, string, string][]>;
}

View File

@@ -0,0 +1,9 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { GlobalHistoryHost } from "./types.ts";
/**
* Shows the global vault history window.
*
* @param host - The service feature host context.
*/
export declare function showGlobalHistory(host: GlobalHistoryHost): void;

View File

@@ -0,0 +1,8 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { GlobalHistoryServices } from "./types.ts";
/**
* A service feature hook that initialises and manages the Global History view.
* Registers the global history view and ribbon command.
*/
export declare const useGlobalHistory: import("@/types.ts").ObsidianServiceFeatureFunction<GlobalHistoryServices, never, "liveSyncPlugin", void>;

View File

@@ -0,0 +1,15 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
/**
* Service keys required by the global history feature.
*/
export type GlobalHistoryServices = "API" | "appLifecycle";
/**
* Service modules required by the global history feature.
*/
export type GlobalHistoryModules = never;
/**
* The host type representing the injected service container with global history capabilities.
*/
export type GlobalHistoryHost = NecessaryObsidianServices<GlobalHistoryServices, never, "liveSyncPlugin">;

View File

@@ -0,0 +1,10 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { HiddenFileSyncHost } from "./types.ts";
export declare function registerHiddenFileSyncCommands(host: HiddenFileSyncHost, handlers: {
isReady: () => boolean;
initialiseInternalFileSync: (mode: "safe", showNotice: boolean) => Promise<void>;
scanAllStorageChanges: (showNotice: boolean) => Promise<boolean>;
scanAllDatabaseChanges: (showNotice: boolean) => Promise<boolean>;
applyOfflineChanges: (showNotice: boolean) => Promise<void>;
}): void;

View File

@@ -0,0 +1,71 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
import type { FilePathWithPrefix, LoadedEntry, MetaEntry, DocumentID } from "@lib/common/types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils";
import type { HiddenFileSyncHost } from "./types.ts";
import type { HiddenFileSyncState } from "./state.ts";
/**
* Enqueues a file path for a conflict check if it is not already pending.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param path - The prefix-marked document path.
*/
export declare function queueConflictCheck(host: HiddenFileSyncHost, state: HiddenFileSyncState, path: FilePathWithPrefix): void;
/**
* Marks a conflict check as finished by removing the path from the pending conflicts set.
*
* @param state - The runtime state of the hidden file synchronisation module.
* @param path - The prefix-marked document path.
*/
export declare function finishConflictCheck(state: HiddenFileSyncState, path: FilePathWithPrefix): void;
/**
* Re-enqueues a file path for conflict check processing, clearing the previous state first.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param path - The prefix-marked document path.
*/
export declare function requeueConflictCheck(host: HiddenFileSyncHost, state: HiddenFileSyncState, path: FilePathWithPrefix): void;
/**
* Scans the database for any conflicted hidden file entries and enqueues them for resolution.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
*/
export declare function resolveConflictOnInternalFiles(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState): Promise<void>;
/**
* Resolves a conflict automatically by keeping the revision with the newer modification timestamp and removing the older one.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param id - The Document ID in the database.
* @param path - The prefix-marked file path.
* @param currentDoc - The current metadata document version.
* @param currentRev - The revision of the current document.
* @param conflictedRev - The conflicted revision to compare.
*/
export declare function resolveByNewerEntry(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, id: DocumentID, path: FilePathWithPrefix, currentDoc: MetaEntry, currentRev: string, conflictedRev: string): Promise<void>;
/**
* Opens a JSON interactive merge dialogue to let the user resolve conflict revisions manually.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param docA - Loaded entry revision A.
* @param docB - Loaded entry revision B.
* @returns A promise resolving to true if the merge dialogue was successfully completed; otherwise, false.
*/
export declare function showJSONMergeDialogAndMerge(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, docA: LoadedEntry, docB: LoadedEntry): Promise<boolean>;
/**
* Creates a QueueProcessor configuration to handle hidden file conflict resolution sequentially.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @returns A QueueProcessor managing file paths with conflicts.
*/
export declare function createConflictResolutionProcessor(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState): QueueProcessor<FilePathWithPrefix, any>; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration

View File

@@ -0,0 +1,131 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { UXFileInfo, UXStat, FilePath, UXDataWriteOptions, MetaEntry, LoadedEntry } from "@lib/common/types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils";
import type { InternalFileInfo } from "@/common/types.ts";
import type { HiddenFileSyncHost } from "./types.ts";
import type { HiddenFileSyncState } from "./state.ts";
/**
* Ensures that the directory structure for a given path exists in the storage.
* If the directory does not exist, it will be created recursively.
*
* @param host - The service feature host providing access to services.
* @param path - The file path for which the parent directories should be ensured.
*/
export declare function ensureDir(host: HiddenFileSyncHost, path: FilePath): Promise<void>;
/**
* Writes data directly to a hidden storage file and returns the updated file metadata.
*
* @param host - The service feature host providing access to services.
* @param path - The destination file path.
* @param data - The text or binary data to be written.
* @param opt - Optional metadata settings such as modification time and creation time.
* @returns The metadata of the written file, or null if the write operation failed.
*/
export declare function writeFile(host: HiddenFileSyncHost, path: FilePath, data: string | ArrayBuffer, opt?: UXDataWriteOptions): Promise<UXStat | null>;
/**
* Internal helper to remove a file from the hidden storage.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param path - The target file path to be removed.
* @returns 'OK' if the file was successfully removed, 'ALREADY' if it did not exist, or false on failure.
*/
export declare function __removeFile(host: HiddenFileSyncHost, log: LogFunction, path: FilePath): Promise<"OK" | "ALREADY" | false>;
/**
* Triggers a storage synchronisation event to notify other modules of a file modification.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param path - The modified file path.
*/
export declare function triggerEvent(host: HiddenFileSyncHost, log: LogFunction, path: FilePath): Promise<void>;
/**
* Internal helper to delete a hidden file and trigger its respective event notifications.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param storageFilePath - The path of the file to be deleted.
* @returns 'OK' if deleted, 'ALREADY' if not found, or false if the operation failed.
*/
export declare function __deleteFile(host: HiddenFileSyncHost, log: LogFunction, storageFilePath: FilePath): Promise<false | "OK" | "ALREADY">;
/**
* Internal helper to check whether a storage file needs to be written by comparing its contents with target data.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param storageFilePath - The path of the storage file.
* @param content - The target content to compare against.
* @returns True if the contents differ or an error occurs; false if they are identical.
*/
export declare function __checkIsNeedToWriteFile(host: HiddenFileSyncHost, log: LogFunction, storageFilePath: FilePath, content: string | ArrayBuffer): Promise<boolean>;
/**
* Internal helper to write a database entry back to a local storage file.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param storageFilePath - The path of the target file in the storage.
* @param fileOnDB - The loaded database entry.
* @param force - If true, writes the file regardless of content equivalence.
* @returns The file metadata on success, or false on failure.
*/
export declare function __writeFile(host: HiddenFileSyncHost, log: LogFunction, storageFilePath: FilePath, fileOnDB: LoadedEntry, force: boolean): Promise<false | UXStat>;
/**
* Loads a hidden file from local storage, wrapping it in a `UXFileInfo` structure.
*
* @param host - The service feature host providing access to services.
* @param path - The local file path.
* @returns A structure containing the file name, path, metadata, and body content.
*/
export declare function loadFileWithInfo(host: HiddenFileSyncHost, path: FilePath): Promise<UXFileInfo>;
/**
* Internal helper to load the base database document entry for a given file.
* Returns a template for a new entry if the file does not exist in the database.
*
* @param host - The service feature host providing access to services.
* @param file - The target file path.
* @param includeContent - Whether to load the content of the document.
* @returns The loaded database entry.
*/
export declare function __loadBaseSaveData(host: HiddenFileSyncHost, file: FilePath, includeContent?: boolean): Promise<LoadedEntry | false>;
/**
* Saves a local hidden file's content and metadata into the database.
* Confirms that the file content has changed before submitting updates to save database storage.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param file - The runtime file description containing metadata and body.
* @param forceWrite - If true, saves the file to the database even if the content is identical.
* @returns True if the update succeeded, undefined if skipped, or false on failure.
*/
export declare function storeInternalFileToDatabase(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, file: InternalFileInfo | UXFileInfo, forceWrite?: boolean): Promise<boolean | undefined>;
/**
* Marks a hidden file as deleted in the database.
* It also cleans up any conflicting revisions associated with the file.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param filenameSrc - The name of the file being deleted.
* @param forceWrite - Unused parameter retained for interface compatibility.
* @returns True if deletion succeeds, undefined if ignored, or false on error.
*/
export declare function deleteInternalFileOnDatabase(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, filenameSrc: FilePath, forceWrite?: boolean): Promise<boolean | undefined>;
/**
* Extracts a hidden file's metadata and content from the database and writes it to local storage.
* Evaluates whether writing is required based on timestamp differences, deletion markings, and conflict states.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param storageFilePath - The local file destination path.
* @param force - If true, ignores cache check optimizations and forces the file to be written.
* @param metaEntry - The pre-fetched metadata of the database document, if available.
* @param preventDoubleProcess - If true, skips processing if this database key revision matches the cache.
* @param onlyNew - If true, writes the file only when the database version has a newer modification time.
* @param includeDeletion - Whether to apply deletion when checking newer times.
* @param queueNotification - Optional callback to queue notification for reload events.
* @returns True if processed successfully, undefined if skipped, or false on failure.
*/
export declare function extractInternalFileFromDatabase(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, storageFilePath: FilePath, force?: boolean, metaEntry?: MetaEntry | LoadedEntry, preventDoubleProcess?: boolean, onlyNew?: boolean, includeDeletion?: boolean, queueNotification?: (key: FilePath) => void): Promise<boolean | undefined>;

View File

@@ -0,0 +1,24 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { FilePath, FilePathWithPrefix, LoadedEntry } from "@lib/common/types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils";
import type { HiddenFileSyncHost } from "./types.ts";
import type { HiddenFileSyncState } from "./state.ts";
export declare function bindHiddenFileSyncEvents(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, handlers: {
updateSettingCache: () => void;
isThisModuleEnabled: () => boolean;
isDatabaseReady: () => boolean;
isReady: () => boolean;
scanAllStorageChanges: (showNotice: boolean) => Promise<boolean>;
performStartupScan: (showNotice: boolean) => Promise<void>;
trackStorageFileModification: (path: FilePath) => Promise<boolean>;
queueConflictCheck: (path: FilePathWithPrefix) => void;
processOptionalSyncFiles: (doc: LoadedEntry) => Promise<boolean>;
suspendExtraSync: () => Promise<boolean>;
askUsingOptionalSyncFeature: (opt: {
enableFetch?: boolean;
enableOverwrite?: boolean;
}) => Promise<boolean>;
configureOptionalSyncFeature: (feature: keyof OPTIONAL_SYNC_FEATURES) => Promise<boolean>;
isTargetFile: (path: FilePath) => Promise<boolean>;
}): void;

View File

@@ -0,0 +1,4 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { HiddenFileSyncModules, HiddenFileSyncServices } from "./types.ts";
export declare const useHiddenFileSync: import("@/types.ts").ObsidianServiceFeatureFunction<HiddenFileSyncServices, HiddenFileSyncModules, "app", void>;

View File

@@ -0,0 +1,68 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { FilePath, MetaEntry } from "@lib/common/types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils";
import type { HiddenFileSyncHost } from "./types.ts";
import type { HiddenFileSyncState } from "./state.ts";
/**
* Adopts the current local storage files as already processed, updating their cache keys to match their actual current file states.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param targetFiles - A list of target files, or false to adopt all local storage files.
*/
export declare function adoptCurrentStorageFilesAsProcessed(host: HiddenFileSyncHost, state: HiddenFileSyncState, targetFiles: FilePath[] | false): Promise<void>;
/**
* Adopts the current database files as already processed, updating their cache keys to match their actual current database states.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param targetFiles - A list of target files, or false to adopt all database files.
*/
export declare function adoptCurrentDatabaseFilesAsProcessed(host: HiddenFileSyncHost, state: HiddenFileSyncState, targetFiles: FilePath[] | false): Promise<void>;
/**
* Compares and merges files between the storage and local database based on their modification timestamps.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param showNotice - Whether to show progress notifications.
* @param targetFiles - A list of target files to merge, or false to merge all.
* @returns A list of all file names processed during the merge.
*/
export declare function rebuildMerging(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, showNotice: boolean, targetFiles?: FilePath[] | false): Promise<FilePath[]>;
/**
* Rebuilds database entries from the local storage files.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param showNotice - Whether to show progress notifications.
* @param targetFiles - A list of target files, or false to process all files.
* @param onlyNew - If true, only updates database records if they are newer than the storage version.
* @returns A list of file paths processed.
*/
export declare function rebuildFromStorage(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, showNotice: boolean, targetFiles?: FilePath[] | false, onlyNew?: boolean): Promise<FilePath[]>;
/**
* Rebuilds local storage files from the database entries.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param showNotice - Whether to show progress notifications.
* @param targetFiles - A list of target files, or false to process all files.
* @param onlyNew - If true, only overwrites local files if the database version is newer.
* @returns A list of metadata entries processed.
*/
export declare function rebuildFromDatabase(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, showNotice: boolean, targetFiles?: FilePath[] | false, onlyNew?: boolean): Promise<MetaEntry[]>;
/**
* Initialises or synchronises the hidden files synchronisation state based on a specified direction.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param direction - The direction of synchronisation ('pull', 'push', 'safe', 'pullForce', or 'pushForce').
* @param showMessage - Whether to display progress status alerts in the UI.
* @param targetFilesSrc - Specific source file paths to synchronise, or false for all.
*/
export declare function initialiseInternalFileSync(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, direction?: "pull" | "push" | "safe" | "pullForce" | "pushForce", showMessage?: boolean, targetFilesSrc?: string[] | false): Promise<void>;

View File

@@ -0,0 +1,46 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils";
import type { HiddenFileSyncHost } from "./types.ts";
import type { HiddenFileSyncState } from "./state.ts";
/**
* Checks whether the hidden file synchronisation module is enabled in the current settings.
*
* @param host - The service feature host providing access to services.
* @returns True if the synchronisation of internal/hidden files is enabled; otherwise, false.
*/
export declare function isThisModuleEnabled(host: HiddenFileSyncHost): boolean;
/**
* Checks whether the local database is ready and available for operations.
*
* @param host - The service feature host providing access to services.
* @returns True if the database is ready; otherwise, false.
*/
export declare function isDatabaseReady(host: HiddenFileSyncHost): boolean;
/**
* Determines if the hidden file synchronisation module is ready to execute.
* It checks if the application lifecycle is ready, is not suspended, and the module is enabled.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @returns True if the module is ready; otherwise, false.
*/
export declare function isReady(host: HiddenFileSyncHost, state: HiddenFileSyncState): boolean;
/**
* Clears the cached configuration and regular expressions when settings are updated.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
*/
export declare function updateSettingCache(host: HiddenFileSyncHost, state: HiddenFileSyncState): void;
/**
* Performs the initial synchronisation scan during startup.
* It invokes the offline changes application handler to process pending local and database modifications.
*
* @param host - The service feature host providing access to services.
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param showNotice - Whether to show system notices for the progress of the operations.
* @param applyOfflineChanges - The callback function to apply offline modifications.
*/
export declare function performStartupScan(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, showNotice: boolean, applyOfflineChanges: (showNotice: boolean) => Promise<void>): Promise<void>;

View File

@@ -0,0 +1,48 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { Semaphore } from "octagonal-wheels/concurrency/semaphore";
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
import { PeriodicProcessor } from "@/common/PeriodicProcessor.ts";
import type { FilePathWithPrefix } from "@lib/common/types.ts";
import type { CustomRegExp } from "@lib/common/utils.ts";
/**
* Represents the mutable runtime state for the hidden file synchronisation module.
*/
export interface HiddenFileSyncState {
/** Processor for executing periodic internal/hidden file scanning. */
periodicInternalFileScanProcessor: PeriodicProcessor | undefined;
/** Map tracking the last processed file key for each local file path. */
_fileInfoLastProcessed: Map<string, string>;
/** Map tracking the last known modification timestamp for each local file path. */
_fileInfoLastKnown: Map<string, number>;
/** Map tracking the last processed database document key for each path. */
_databaseInfoLastProcessed: Map<string, string>;
/** Map tracking the last known database document timestamp for each path. */
_databaseInfoLastKnown: Map<string, number>;
/** Unused map for tracking deleted files. */
_databaseInfoLastDeleted: Map<string, string>;
/** Unused map for tracking deleted file timestamps. */
_databaseInfoLastKnownDeleted: Map<string, number>;
/** Semaphore to serialize operations on individual files and prevent race conditions. */
semaphore: ReturnType<typeof Semaphore>;
/** Set containing the prefix-marked document paths currently pending conflict checks. */
pendingConflictChecks: Set<FilePathWithPrefix>;
/** Processor executing the conflict resolution queue sequentially. */
conflictResolutionProcessor: QueueProcessor<FilePathWithPrefix, void> | undefined;
/** Cached regular expressions for file matching settings. */
cacheFileRegExps: Map<string, CustomRegExp[][]>;
/** Cached ignore file paths dictated by customisation sync. */
cacheCustomisationSyncIgnoredFiles: Map<string, string[]>;
/** Queued folder paths that have changed and require reload notification. */
queuedNotificationFiles: Set<string>;
/** Whether the synchronisation operations are temporarily suspended. */
suspended: boolean;
/** Notice count index for progress keys. */
noticeIndex: number;
}
/**
* Creates and initialises a new runtime state object for the hidden file synchronisation feature.
*
* @returns An initialised HiddenFileSyncState object.
*/
export declare function createHiddenFileSyncState(): HiddenFileSyncState;

View File

@@ -0,0 +1,131 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type MetaEntry, type LoadedEntry, type UXFileInfo, type UXStat, type FilePath } from "@lib/common/types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils";
import type { HiddenFileSyncHost } from "./types.ts";
import type { HiddenFileSyncState } from "./state.ts";
/**
* Extracts the modification timestamp (mtime) from various entry types for comparison.
* If the entry represents a deleted file, it returns 0 unless `includeDeleted` is true.
*
* @param doc - The document entry or file info stat.
* @param includeDeleted - Whether to return mtime for deleted entries.
* @returns The modification timestamp, or 0 if empty or deleted.
*/
export declare function getComparingMTime(doc: (MetaEntry | LoadedEntry | false) | UXFileInfo | UXStat | null | undefined, includeDeleted?: boolean): number;
/**
* Converts a storage file stat object into a unique cache key representation.
*
* @param stat - The storage file metadata.
* @returns A string key in the format: "mtime-size".
*/
export declare function statToKey(stat: UXStat | null): string;
/**
* Converts a database document entry into a unique cache key representation.
*
* @param doc - The database document metadata or loaded entry.
* @returns A string key representing mtime, size, revision, and deletion status.
*/
export declare function docToKey(doc: LoadedEntry | MetaEntry): string;
/**
* Calculates the storage metadata key for a given file path.
*
* @param host - The service feature host providing access to services.
* @param file - The target file path.
* @param stat - Pre-fetched metadata stat, if available.
* @returns The calculated key string.
*/
export declare function fileToStatKey(host: HiddenFileSyncHost, file: FilePath, stat?: UXStat | null): Promise<string>;
/**
* Updates the cached state for the last processed storage file metadata.
*
* @param state - The runtime state of the hidden file synchronisation module.
* @param file - The target file path.
* @param keySrc - The metadata stat or key string representation to cache.
*/
export declare function updateLastProcessedFile(state: HiddenFileSyncState, file: FilePath, keySrc: string | UXStat): void;
/**
* Fetches file stats from the storage and updates the cached state for the last processed file.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param file - The target file path.
* @param stat - Pre-fetched metadata stat, if available.
*/
export declare function updateLastProcessedAsActualFile(host: HiddenFileSyncHost, state: HiddenFileSyncState, file: FilePath, stat?: UXStat | null): Promise<void>;
/**
* Clears the last processed storage cache marks for target files or all files.
*
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param targetFiles - A list of target files, or false to clear all cached marks.
*/
export declare function resetLastProcessedFile(log: LogFunction, state: HiddenFileSyncState, targetFiles: FilePath[] | false): void;
/**
* Retrieves the modification timestamp of the last processed storage file.
*
* @param state - The runtime state of the hidden file synchronisation module.
* @param file - The target file path.
* @returns The cached modification timestamp.
*/
export declare function getLastProcessedFileMTime(state: HiddenFileSyncState, file: FilePath): number;
/**
* Retrieves the cache key for the last processed storage file.
*
* @param state - The runtime state of the hidden file synchronisation module.
* @param file - The target file path.
* @returns The cached key string.
*/
export declare function getLastProcessedFileKey(state: HiddenFileSyncState, file: FilePath): string | undefined;
/**
* Retrieves the cache key for the last processed database document.
*
* @param state - The runtime state of the hidden file synchronisation module.
* @param file - The target file path.
* @returns The cached key string.
*/
export declare function getLastProcessedDatabaseKey(state: HiddenFileSyncState, file: FilePath): string | undefined;
/**
* Updates the cached state for the last processed database document key.
*
* @param state - The runtime state of the hidden file synchronisation module.
* @param file - The target file path.
* @param keySrc - The database document metadata or key representation to cache.
*/
export declare function updateLastProcessedDatabase(state: HiddenFileSyncState, file: FilePath, keySrc: string | MetaEntry | LoadedEntry): void;
/**
* Updates both storage file and database cache records for a path, registering changes in the path manager.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param path - The target file path.
* @param db - The loaded database document entry.
* @param stat - The storage metadata status.
*/
export declare function updateLastProcessed(host: HiddenFileSyncHost, state: HiddenFileSyncState, path: FilePath, db: MetaEntry | LoadedEntry, stat: UXStat): void;
/**
* Updates both storage file and database cache records for a path to represent deletion, clearing path manager records.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param path - The target file path.
* @param db - The database entry representing deletion, or false if not stored.
*/
export declare function updateLastProcessedDeletion(host: HiddenFileSyncHost, state: HiddenFileSyncState, path: FilePath, db: MetaEntry | LoadedEntry | false): void;
/**
* Fetches database document metadata and updates the database cache key for the path.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param file - The target file path.
* @param doc - Optional pre-fetched metadata of the database document.
*/
export declare function updateLastProcessedAsActualDatabase(host: HiddenFileSyncHost, state: HiddenFileSyncState, file: FilePath, doc?: MetaEntry | LoadedEntry | null | false): Promise<void>;
/**
* Clears the last processed database cache marks for target files or all files.
*
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param targetFiles - A list of target files, or false to clear all cached marks.
*/
export declare function resetLastProcessedDatabase(log: LogFunction, state: HiddenFileSyncState, targetFiles: FilePath[] | false): void;

View File

@@ -0,0 +1,289 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { FilePath, LoadedEntry, MetaEntry, DocumentID } from "@lib/common/types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils";
import { type CustomRegExp } from "@lib/common/utils.ts";
import type { HiddenFileSyncHost } from "./types.ts";
import type { HiddenFileSyncState } from "./state.ts";
/**
* Generates a progress logger that tracks long-running synchronisation operations.
*
* @param log - The logging function.
* @param state - The runtime state of the hidden file synchronisation module.
* @param prefix - The message prefix to prepend to log statements.
* @param level - The log level to use.
* @returns An object containing `log`, `once`, and `done` progress log methods.
*/
export declare function getProgress(log: LogFunction, state: HiddenFileSyncState, prefix?: string, level?: any): { // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration
log: (msg: string) => void;
once: (msg: string) => void;
done: (msg?: string) => void;
};
/**
* Parses ignore and target custom regular expression filters from settings, caching the compiled filters.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @returns Compiled regular expressions for target and ignored files.
*/
export declare function parseRegExpSettings(host: HiddenFileSyncHost, state: HiddenFileSyncState): {
ignoreFilter: CustomRegExp[];
targetFilter: CustomRegExp[];
};
/**
* Checks if a given file path is matched by target patterns and not ignored by ignore patterns.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param path - The file path to check.
* @returns True if the path is a synchronisation target based on pattern settings; otherwise, false.
*/
export declare function isTargetFileInPatterns(host: HiddenFileSyncHost, state: HiddenFileSyncState, path: string): boolean;
/**
* Determines which files are synchronised by the customisation sync feature and should be ignored by this module.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @returns A list of ignored file path strings.
*/
export declare function getCustomisationSynchronizationIgnoredFiles(host: HiddenFileSyncHost, state: HiddenFileSyncState): string[];
/**
* Checks whether a path is not ignored due to customisation synchronisation settings.
*
* @param host - The service feature host providing access to services.
* @param state - The runtime state of the hidden file synchronisation module.
* @param path - The file path to check.
* @returns True if not ignored by customisation synchronisation; otherwise, false.
*/
export declare function isNotIgnoredByCustomisationSync(host: HiddenFileSyncHost, state: HiddenFileSyncState, path: string): boolean;
/**
* Verifies if the path represents a hidden configuration file.
* Configuration files start with '.' and are not within the '.trash' folder.
*
* @param path - The file path to verify.
* @returns True if the path represents a hidden file; otherwise, false.
*/
export declare function isHiddenFileSyncHandlingPath(path: FilePath): boolean;
/**
* Validates if the path is a synchronisation target, checking pattern filters, customisation sync rules, hidden file rules, and ignore file rules.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param path - The target file path.
* @returns True if the file should be synchronised; otherwise, false.
*/
export declare function isTargetFile(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, path: FilePath): Promise<boolean>;
/**
* Executes a function sequentially for an event using locks and semaphores to prevent race conditions during file processing.
*
* @param host - The service feature host.
* @param state - The runtime state.
* @param file - The file path.
* @param fn - The function to run.
*/
export declare function serializedForEvent<T>(host: HiddenFileSyncHost, state: HiddenFileSyncState, file: FilePath, fn: () => Promise<T>): Promise<T>;
/**
* Recursively lists files inside the specified directory path that pass the verification check function.
*
* @param host - The service feature host.
* @param state - The runtime state.
* @param path - The directory path to list.
* @param checkFunction - The verification callback.
* @returns A list of file paths.
*/
export declare function getFiles(host: HiddenFileSyncHost, state: HiddenFileSyncState, path: string, checkFunction: (path: FilePath) => Promise<boolean> | boolean): Promise<string[]>;
/**
* Scans the local workspace vault for hidden configuration files that are target synchronisation candidates.
*
* @param host - The service feature host.
* @param state - The runtime state.
* @returns A list of hidden file paths.
*/
export declare function scanInternalFileNames(host: HiddenFileSyncHost, state: HiddenFileSyncState): Promise<FilePath[]>;
/**
* Queries the local database for all hidden configuration file metadata documents.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @returns A list of database metadata entries.
*/
export declare function getAllDatabaseFiles(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState): Promise<MetaEntry[]>;
/**
* Tracks scanned storage changes, synchronising them to the database in bulk.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param processFiles - The list of local files to process.
* @param showNotice - Whether to show system notices.
* @param onlyNew - If true, only updates database files if they are newer.
* @param forceWriteAll - If true, forces database updates.
* @param includeDeleted - Whether to process deleted files.
*/
export declare function trackScannedStorageChanges(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, processFiles: FilePath[], showNotice?: boolean, onlyNew?: boolean, forceWriteAll?: boolean, includeDeleted?: boolean): Promise<void>;
/**
* Scans all local storage files and compares them with the cache to track any new changes to be saved to the database.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param showNotice - Whether to show progress notices.
* @param onlyNew - If true, only synchronises newer files.
* @param forceWriteAll - If true, forces file updates.
* @param includeDeleted - Whether to process deleted files.
* @returns True if scanning and updates succeeded; otherwise, false.
*/
export declare function scanAllStorageChanges(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, showNotice?: boolean, onlyNew?: boolean, forceWriteAll?: boolean, includeDeleted?: boolean): Promise<boolean>;
/**
* Tracks a single storage file modification, saving updates or deleting database records accordingly.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param path - The local storage path.
* @param onlyNew - If true, only updates the database if the storage file is newer.
* @param forceWrite - If true, forces database updates.
* @param includeDeleted - Whether to track deletions.
* @returns True if modification tracking succeeded, or false if skipped/failed.
*/
export declare function trackStorageFileModification(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, path: FilePath, onlyNew?: boolean, forceWrite?: boolean, includeDeleted?: boolean): Promise<boolean | undefined>;
/**
* Applies offline database and storage modifications by comparing differences on untracked files.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param showNotice - Whether to show notifications.
*/
export declare function applyOfflineChanges(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, showNotice: boolean): Promise<void>;
/**
* Tracks scanned database changes, writing updates to the local storage in bulk.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param processFiles - Database entries to track.
* @param showNotice - Whether to show notices.
* @param onlyNew - If true, only overwrites local files if the database entry is newer.
* @param forceWriteAll - If true, forces local file updates.
* @param includeDeletion - Whether to apply database deletions.
*/
export declare function trackScannedDatabaseChange(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, processFiles: MetaEntry[], showNotice?: boolean, onlyNew?: boolean, forceWriteAll?: boolean, includeDeletion?: boolean): Promise<void>;
/**
* Scans the database for changed metadata documents to update the local storage.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param showNotice - Whether to show notices.
* @param onlyNew - If true, only updates the local storage if database changes are newer.
* @param forceWriteAll - If true, forces storage updates.
* @param includeDeletion - Whether to apply deletions.
* @returns True if database scan and application succeeded; otherwise, false.
*/
export declare function scanAllDatabaseChanges(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, showNotice?: boolean, onlyNew?: boolean, forceWriteAll?: boolean, includeDeletion?: boolean): Promise<boolean>;
/**
* Processes a single database file modification, resolving conflicts or updating the local storage.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param storageFilePath - The local file path.
* @param reason - The log context string.
* @param preventDoubleProcess - If true, skips processing if this database key revision matches the cache.
* @param onlyNew - If true, only overwrites if database entries are newer.
* @param metaEntry - Pre-fetched database metadata, if available.
* @param includeDeletion - Whether to apply database deletions.
* @returns True if database tracking succeeded.
*/
export declare function trackDatabaseFileModification(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, storageFilePath: FilePath, reason: string, preventDoubleProcess: boolean, onlyNew: boolean, metaEntry?: MetaEntry | LoadedEntry, includeDeletion?: boolean): Promise<boolean | undefined>;
/**
* Event handler triggered when synchronised files change in the database.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param doc - The loaded database document entry.
* @returns True if database change processing was handled; otherwise, false.
*/
export declare function processOptionalSyncFiles(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, doc: LoadedEntry): Promise<boolean>;
/**
* Extracts and formats key metadata properties from a database document.
*
* @param host - The service feature host.
* @param doc - The database document metadata or loaded entry.
* @returns Formatted metadata property strings.
*/
export declare function getDocProps(host: HiddenFileSyncHost, doc: MetaEntry | LoadedEntry): {
id: DocumentID;
rev: string;
revDisplay: string;
prefixedPath: DocumentID;
path: FilePath;
isDeleted: boolean;
shortenedId: string;
shortenedPath: string;
};
/**
* Extracts the numerical revision sequence prefix from a PouchDB revision string.
*
* @param rev - The PouchDB revision string.
* @returns The numerical prefix string of the revision.
*/
export declare function displayRev(rev: string): string;
/**
* Returns a callback wrapper that invokes the inner function only once every N invocations.
*
* @param n - The step frequency threshold.
* @param func - The inner function callback.
* @returns The step count logging wrapper function.
*/
export declare function onlyInNTimes(n: number, func: (progress: number) => void): () => void;
/**
* Queues folder change notifications to warn the user about plugin or configuration updates.
*
* @param host - The service feature host.
* @param state - The runtime state.
* @param key - The file path that was updated.
*/
export declare function queueNotification(host: HiddenFileSyncHost, state: HiddenFileSyncState, key: FilePath): void;
/**
* Triggers user notifications and prompt dialogues for reloading plug-ins or reloading the Obsidian application.
*
* @param host - The service feature host.
* @param state - The runtime state.
*/
export declare function notifyConfigChange(host: HiddenFileSyncHost, state: HiddenFileSyncState): void;
/**
* Temporarily suspends hidden file synchronisation settings during initial replications.
*
* @param host - The service feature host.
* @param state - The runtime state.
* @returns True if setting change was applied.
*/
export declare function suspendExtraSync(host: HiddenFileSyncHost, state: HiddenFileSyncState): Promise<boolean>;
/**
* Prompts the user with dialogue choices to configure hidden file synchronisation modes.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param opt - Configuration options specifying available modes.
* @returns True if configuration completed.
*/
export declare function askUsingOptionalSyncFeature(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, opt: {
enableFetch?: boolean;
enableOverwrite?: boolean;
}): Promise<boolean>;
/**
* Applies settings and initialises synchronisation based on the selected mode.
*
* @param host - The service feature host.
* @param log - The logging function.
* @param state - The runtime state.
* @param feature - The selected configuration feature mode ('FETCH', 'OVERWRITE', 'MERGE', 'DISABLE', or 'DISABLE_HIDDEN').
* @returns True if setting change was applied; otherwise, false.
*/
export declare function configureOptionalSyncFeature(host: HiddenFileSyncHost, log: LogFunction, state: HiddenFileSyncState, feature: keyof any): Promise<boolean>; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration

View File

@@ -0,0 +1,6 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
export type HiddenFileSyncServices = "API" | "appLifecycle" | "setting" | "vault" | "path" | "database" | "databaseEvents" | "fileProcessing" | "keyValueDB" | "replication" | "conflict" | "control";
export type HiddenFileSyncModules = "storageAccess" | "fileHandler";
export type HiddenFileSyncHost = NecessaryObsidianServices<HiddenFileSyncServices, HiddenFileSyncModules, "app">;

View File

@@ -0,0 +1,38 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type FilePathWithPrefix, type diff_result } from "@lib/common/types.ts";
import type { ConflictResolverHost } from "./types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils";
/**
* Resolves a conflict using the user interface modal, one-by-one.
*
* @param host - The service feature host context.
* @param log - The logger function.
* @param filename - The path of the conflicted file.
* @param conflictCheckResult - The result of conflict detection / diff.
* @returns A promise resolving to true if successfully resolved, otherwise false.
*/
export declare function resolveConflictByUI(host: ConflictResolverHost, log: LogFunction, filename: FilePathWithPrefix, conflictCheckResult: diff_result): Promise<boolean>;
/**
* Iteratively prompts the user to resolve all conflicted files.
*
* @param host - The service feature host context.
* @param log - The logger function.
*/
export declare function allConflictCheck(host: ConflictResolverHost, log: LogFunction): Promise<void>;
/**
* Prompts the user to pick a file from the list of conflicted files.
*
* @param host - The service feature host context.
* @param log - The logger function.
* @returns A promise resolving to true if a file was selected and queued for checking, otherwise false.
*/
export declare function pickFileForResolve(host: ConflictResolverHost, log: LogFunction): Promise<boolean>;
/**
* Scans the database for conflicted files and displays a safety popup if any are found.
*
* @param host - The service feature host context.
* @param log - The logger function.
* @returns A promise resolving to true if execution completes successfully, otherwise false.
*/
export declare function allScanStat(host: ConflictResolverHost, log: LogFunction): Promise<boolean>;

View File

@@ -0,0 +1,8 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { ConflictResolverServices } from "./types.ts";
/**
* A service feature hook that initialises and manages the Interactive Conflict Resolver.
* Registers conflict resolution commands and handles user-interactive resolution flows.
*/
export declare const useInteractiveConflictResolver: import("@/types.ts").ObsidianServiceFeatureFunction<ConflictResolverServices, "databaseFileAccess", "app", void>;

View File

@@ -0,0 +1,15 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
/**
* A union of service keys required by the interactive conflict resolver feature.
*/
export type ConflictResolverServices = "API" | "setting" | "UI" | "database" | "conflict" | "appLifecycle" | "replication" | "path";
/**
* A union of service module keys required by the interactive conflict resolver feature.
*/
export type ConflictResolverModules = "databaseFileAccess";
/**
* The host type representing the injected service container with conflict resolution capabilities.
*/
export type ConflictResolverHost = NecessaryObsidianServices<ConflictResolverServices, ConflictResolverModules, "app">;

View File

@@ -0,0 +1,7 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFeatureServices } from "./types.ts";
/**
* A service feature hook that initialises and manages logging, status display, and debug report generation.
*/
export declare const useLogFeature: import("@/types.ts").ObsidianServiceFeatureFunction<LogFeatureServices, "storageAccess", "app" | "liveSyncPlugin", void>;

View File

@@ -0,0 +1,18 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type LOG_LEVEL } from "@lib/common/types.ts";
import type { LogFeatureHost } from "./types.ts";
import type { LogFeatureState } from "./state.ts";
export declare const MARK_DONE = "\u2009\u2009";
export declare function addLog(state: LogFeatureState, log: string): void;
export declare function addDisplayLog(state: LogFeatureState, log: string): void;
export declare function redactLog(log: string): string;
export declare function writeLogToTheFile(host: LogFeatureHost, now: Date, vaultName: string, newMessage: string): void;
export declare function processAddLog(host: LogFeatureHost, state: LogFeatureState, message: unknown, level?: LOG_LEVEL, key?: string): void;
export declare function adjustStatusDivPosition(host: LogFeatureHost, state: LogFeatureState): void;
export declare function getActiveFileStatus(host: LogFeatureHost): Promise<string>;
export declare function setFileStatus(host: LogFeatureHost, state: LogFeatureState): Promise<void>;
export declare function updateMessageArea(host: LogFeatureHost, state: LogFeatureState): Promise<void>;
export declare function onActiveLeafChange(host: LogFeatureHost, state: LogFeatureState): void;
export declare function applyStatusBarText(host: LogFeatureHost, state: LogFeatureState): void;
export declare function observeForLogs(host: LogFeatureHost, state: LogFeatureState): void;

View File

@@ -0,0 +1,42 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { reactiveSource, type ReactiveValue } from "octagonal-wheels/dataobject/reactive";
import { P2PLogCollector } from "@lib/replication/trystero/P2PLogCollector.ts";
import { Notice } from "@/deps.ts";
import type { LogEntry } from "@lib/mock_and_interop/stores.ts";
/**
* Interface representing the internal state of the logging and status display feature.
*/
export interface LogFeatureState {
statusBar?: HTMLElement;
statusDiv?: HTMLElement;
statusLine?: HTMLDivElement;
logMessage?: HTMLDivElement;
logHistory?: HTMLDivElement;
messageArea?: HTMLDivElement;
statusBarLabels?: ReactiveValue<{
message: string;
status: string;
}>;
statusLog: ReturnType<typeof reactiveSource<string>>;
activeFileStatus: ReturnType<typeof reactiveSource<string>>;
notifies: {
[key: string]: {
notice: Notice;
count: number;
};
};
p2pLogCollector: P2PLogCollector;
nextFrameQueue?: number;
logLines: {
ttl: number;
message: string;
}[];
recentLogEntries: ReturnType<typeof reactiveSource<LogEntry[]>>;
logForDump: string[];
logForDisplay: string[];
}
/**
* Creates the initial state object.
*/
export declare function createInitialState(): LogFeatureState;

View File

@@ -0,0 +1,15 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
/**
* Service keys required by the logging and status bar feature.
*/
export type LogFeatureServices = "API" | "setting" | "replication" | "conflict" | "fileProcessing" | "appLifecycle" | "vault" | "replicator" | "UI";
/**
* Service modules required by the logging and status bar feature.
*/
export type LogFeatureModules = "storageAccess";
/**
* The host type representing the injected service container with logging capabilities.
*/
export type LogFeatureHost = NecessaryObsidianServices<LogFeatureServices, LogFeatureModules, "app" | "liveSyncPlugin">;

View File

@@ -0,0 +1,4 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { MigrationModules, MigrationServices } from "./types.ts";
export declare const useMigrationFeature: import("@/types.ts").ObsidianServiceFeatureFunction<MigrationServices, MigrationModules, never, void>;

View File

@@ -0,0 +1,12 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { MigrationHost } from "./types.ts";
export declare function migrateUsingDoctor(host: MigrationHost, skipRebuild?: boolean, activateReason?: string, forceRescan?: boolean): Promise<boolean>;
export declare function migrateDisableBulkSend(host: MigrationHost, log: LogFunction): Promise<void>;
export declare function initialMigrationMessage(): Promise<boolean>;
export declare function askAgainForSetupURI(host: MigrationHost): Promise<boolean>;
export declare function hasIncompleteDocs(host: MigrationHost, log: LogFunction, force?: boolean): Promise<boolean>;
export declare function hasCompromisedChunks(host: MigrationHost, log: LogFunction): Promise<boolean>;
export declare function runFirstInitialiseMigration(host: MigrationHost, log: LogFunction): Promise<boolean>;
export declare function bindMigrationRequestEvents(host: MigrationHost, log: LogFunction): Promise<boolean>;

View File

@@ -0,0 +1,6 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
export type MigrationServices = "API" | "appLifecycle" | "setting" | "database" | "path" | "vault" | "replicator" | "UI" | "keyValueDB";
export type MigrationModules = "storageAccess" | "fileHandler" | "rebuilder";
export type MigrationHost = NecessaryObsidianServices<MigrationServices, MigrationModules>;

View File

@@ -0,0 +1,21 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type TFile } from "@/deps.ts";
import type { FilePathWithPrefix, DocumentID } from "@lib/common/types.ts";
import type { DocumentHistoryHost } from "./types.ts";
import type { LogFunction } from "@lib/services/lib/logUtils";
/**
* Opens the document history modal dialogue for a given file.
*
* @param host - The service feature host context.
* @param file - The file path or TFile reference to query history.
* @param id - Optional CouchDB document identifier.
*/
export declare function showHistory(host: DocumentHistoryHost, file: TFile | FilePathWithPrefix, id?: DocumentID): void;
/**
* Displays a list of all local documents, prompting the user to select one to view its history.
*
* @param host - The service feature host context.
* @param log - The logger function.
*/
export declare function fileHistory(host: DocumentHistoryHost, log: LogFunction): Promise<void>;

View File

@@ -0,0 +1,8 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { DocumentHistoryServices } from "./types.ts";
/**
* A service feature hook that initialises and manages Obsidian Document History commands.
* Registers ribbon commands and listens to history request events.
*/
export declare const useObsidianDocumentHistory: import("@/types.ts").ObsidianServiceFeatureFunction<DocumentHistoryServices, never, "app" | "liveSyncPlugin", void>;

View File

@@ -0,0 +1,15 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
/**
* Service keys required by the Obsidian document history feature.
*/
export type DocumentHistoryServices = "API" | "vault" | "database" | "UI" | "path" | "appLifecycle";
/**
* Service modules required by the Obsidian document history feature.
*/
export type DocumentHistoryModules = never;
/**
* The host type representing the injected service container with document history capabilities.
*/
export type DocumentHistoryHost = NecessaryObsidianServices<DocumentHistoryServices, DocumentHistoryModules, "app" | "liveSyncPlugin">;

View File

@@ -0,0 +1,34 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { ObsidianEventsHost } from "./types.ts";
import type { ObsidianEventsState } from "./state.ts";
/**
* Executes a restart and reload of the Obsidian application.
*
* @param host - The service container host.
*/
export declare function performAppReload(host: ObsidianEventsHost): void;
/**
* Asks the user if they want to restart and reload Obsidian now, scheduling or executing it.
*
* @param host - The service container host.
* @param log - The logger function.
* @param message - An optional custom message to display in the dialogue.
*/
export declare function askReload(host: ObsidianEventsHost, log: LogFunction, message?: string): void;
/**
* Schedules an application reload, waiting for all background tasks to stabilise to 0.
*
* @param host - The service container host.
* @param log - The logger function.
* @param state - The runtime state of the Obsidian events module.
*/
export declare function scheduleAppReload(host: ObsidianEventsHost, log: LogFunction, state: ObsidianEventsState): void;
/**
* Checks if an application reload has already been scheduled.
*
* @param state - The runtime state of the Obsidian events module.
* @returns True if scheduled, false otherwise.
*/
export declare function isReloadingScheduled(state: ObsidianEventsState): boolean;

View File

@@ -0,0 +1,9 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { ObsidianEventsState } from "./state.ts";
import type { ObsidianEventsHost } from "./types.ts";
export declare function registerVaultAndWorkspaceEvents(host: ObsidianEventsHost): Promise<boolean>;
export declare function registerWindowWatchEvents(host: ObsidianEventsHost, log: LogFunction, state: ObsidianEventsState): void;
export declare function onObsidianEventsLayoutReady(host: ObsidianEventsHost, log: LogFunction, state: ObsidianEventsState): Promise<boolean>;
export declare function bindObsidianEventsLifecycle(host: ObsidianEventsHost, log: LogFunction, state: ObsidianEventsState): void;

View File

@@ -0,0 +1,8 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { ObsidianEventsServices } from "./types.ts";
/**
* A service feature hook that initialises and manages Obsidian application event bindings.
* This hooks into vault file changes, window focus, visibility states, and schedules restarts.
*/
export declare const useObsidianEvents: import("@/types.ts").ObsidianServiceFeatureFunction<ObsidianEventsServices, never, "plugin" | "app", void>;

View File

@@ -0,0 +1,13 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { ObsidianEventsHost } from "./types.ts";
import type { ObsidianEventsState } from "./state.ts";
/**
* Swaps the default Obsidian save command callback to trigger a synchronisation sweep.
*
* @param host - The service container host.
* @param log - The logger function.
* @param state - The runtime state of the Obsidian events module.
*/
export declare function swapSaveCommand(host: ObsidianEventsHost, log: LogFunction, state: ObsidianEventsState): void;

View File

@@ -0,0 +1,18 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type ReactiveSource } from "octagonal-wheels/dataobject/reactive";
/**
* Represents the runtime state of the Obsidian events module.
*/
export interface ObsidianEventsState {
initialCallback: (() => void) | undefined;
hasFocus: boolean;
isLastHidden: boolean;
totalProcessingCount: ReactiveSource<number> | undefined;
}
/**
* Creates and initialises a new Obsidian events state object.
*
* @returns A freshly initialised {@link ObsidianEventsState} object.
*/
export declare function createObsidianEventsState(): ObsidianEventsState;

View File

@@ -0,0 +1,15 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
/**
* A union of service keys required by the Obsidian events management feature.
*/
export type ObsidianEventsServices = "API" | "setting" | "appLifecycle" | "control" | "replication" | "vault" | "fileProcessing" | "conflict" | "database" | "UI";
/**
* A union of service module keys required by the Obsidian events management feature.
*/
export type ObsidianEventsModules = never;
/**
* The host type representing the injected service container with Obsidian events capabilities.
*/
export type ObsidianEventsHost = NecessaryObsidianServices<ObsidianEventsServices, ObsidianEventsModules, "app" | "plugin">;

View File

@@ -0,0 +1,60 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { TFile } from "@/deps.ts";
import type { LogFunction } from "@lib/services/lib/logUtils.ts";
import type { ObsidianEventsHost } from "./types.ts";
import type { ObsidianEventsState } from "./state.ts";
/**
* Sets the focus status and triggers visibility check scheduling.
*
* @param host - The service container host.
* @param log - The logger function.
* @param state - The runtime state of the Obsidian events module.
* @param hasFocus - The new focus status.
*/
export declare function setHasFocus(host: ObsidianEventsHost, log: LogFunction, state: ObsidianEventsState, hasFocus: boolean): void;
/**
* Schedules a task to check and apply window visibility transitions.
*
* @param host - The service container host.
* @param log - The logger function.
* @param state - The runtime state of the Obsidian events module.
*/
export declare function watchWindowVisibility(host: ObsidianEventsHost, log: LogFunction, state: ObsidianEventsState): void;
/**
* Asynchronously processes window visibility transitions, suspending or resuming replication channels.
*
* @param host - The service container host.
* @param log - The logger function.
* @param state - The runtime state of the Obsidian events module.
*/
export declare function watchWindowVisibilityAsync(host: ObsidianEventsHost, log: LogFunction, state: ObsidianEventsState): Promise<void>;
/**
* Schedules a task to check online recovery and vault rescanning.
*
* @param host - The service container host.
* @param log - The logger function.
*/
export declare function watchOnline(host: ObsidianEventsHost, log: LogFunction): void;
/**
* Asynchronously checks if online recovery is required, performing a vault scan if the network recovers.
*
* @param host - The service container host.
*/
export declare function watchOnlineAsync(host: ObsidianEventsHost): Promise<void>;
/**
* Schedules a task to process files opened in the workspace.
*
* @param host - The service container host.
* @param log - The logger function.
* @param file - The file that was opened.
*/
export declare function watchWorkspaceOpen(host: ObsidianEventsHost, log: LogFunction, file: TFile | null): void;
/**
* Asynchronously handles workspace file open events, running replication and checking for conflicts.
*
* @param host - The service container host.
* @param log - The logger function.
* @param file - The file that was opened.
*/
export declare function watchWorkspaceOpenAsync(host: ObsidianEventsHost, log: LogFunction, file: TFile): Promise<void>;

View File

@@ -0,0 +1,8 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
/**
* Obsidian Menu Feature
*
* Provides Obsidian-specific UI elements like ribbon icons and commands.
*/
export declare const useObsidianMenuFeature: import("@/types.ts").ObsidianServiceFeatureFunction<"setting" | "replication" | "control" | "appLifecycle" | "API" | "fileProcessing" | "conflict", never, "plugin", void>;

View File

@@ -0,0 +1,32 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type ObsidianLiveSyncSettings } from "@lib/common/types.ts";
export declare const SETTING_HEADER = "````yaml:livesync-setting\n";
export declare const SETTING_FOOTER = "\n````";
/**
* Extracts the YAML settings block from the full text of a markdown file.
*
* Returns the preamble (text before the block), the body (YAML content), and
* the postscript (text after the block). If no block is found, the entire
* `data` string is returned as the preamble with empty body and postscript.
*/
export declare const extractSettingFromWholeText: (data: string) => {
preamble: string;
body: string;
postscript: string;
};
/**
* Strips sensitive / internal-only fields from a settings snapshot so that it
* is safe to serialise into a markdown file.
*
* If `keepCredential` is true (or `writeCredentialsForSettingSync` is set on
* the settings object) the credential fields are retained; otherwise they are
* removed.
*/
export declare const generateSettingForMarkdownPure: (settings: ObsidianLiveSyncSettings, keepCredential?: boolean) => Partial<ObsidianLiveSyncSettings>;
/**
* Obsidian Settings as Markdown Feature
*
* Allows saving and loading settings to/from a markdown file.
*/
export declare const useObsidianSettingAsMarkdownFeature: import("@/types.ts").ObsidianServiceFeatureFunction<"setting" | "UI" | "appLifecycle" | "API", "storageAccess" | "rebuilder", "plugin", void>;

View File

@@ -0,0 +1,7 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { SettingDialogueServices } from "./types.ts";
/**
* A service feature hook that registers the plug-in setting tab and listens to settings dialogue triggers.
*/
export declare const useObsidianSettingDialogue: import("@/types.ts").ObsidianServiceFeatureFunction<SettingDialogueServices, never, "app" | "liveSyncPlugin", void>;

View File

@@ -0,0 +1,17 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { SettingDialogueHost } from "./types.ts";
import type { SettingDialogueState } from "./state.ts";
/**
* Opens the Obsidian settings panel and navigates to the Self-hosted LiveSync tab.
*
* @param host - The service feature host context.
*/
export declare function openSetting(host: SettingDialogueHost): void;
/**
* Opens settings and automatically launches the minimal setup configuration wizard.
*
* @param host - The service feature host context.
* @param state - The state object holding the settings tab reference.
*/
export declare function openSettingWizard(host: SettingDialogueHost, state: SettingDialogueState): Promise<void>;

View File

@@ -0,0 +1,13 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { ObsidianLiveSyncSettingTab } from "@/modules/features/SettingDialogue/ObsidianLiveSyncSettingTab.ts";
/**
* Interface representing the internal state of the setting dialogue feature.
*/
export interface SettingDialogueState {
settingTab?: ObsidianLiveSyncSettingTab;
}
/**
* Creates the initial state object.
*/
export declare function createInitialState(): SettingDialogueState;

View File

@@ -0,0 +1,15 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryObsidianServices } from "@/types.ts";
/**
* Service keys required by the Obsidian setting tab dialogue feature.
*/
export type SettingDialogueServices = "API" | "appLifecycle";
/**
* Service modules required by the Obsidian setting tab dialogue feature.
*/
export type SettingDialogueModules = never;
/**
* The host type representing the injected service container with setting tab capabilities.
*/
export type SettingDialogueHost = NecessaryObsidianServices<SettingDialogueServices, SettingDialogueModules, "app" | "liveSyncPlugin">;

View File

@@ -0,0 +1,3 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
export { usePeriodicReplication } from "./periodicReplication";

View File

@@ -0,0 +1,11 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { PeriodicProcessor } from "@/common/PeriodicProcessor";
import { type NecessaryObsidianFeature } from "@/types";
export type PeriodicReplicationHost = NecessaryObsidianFeature<"appLifecycle" | "setting" | "replication" | "control" | "API">;
export declare const disablePeriodicHandler: (processor: PeriodicProcessor | undefined) => Promise<boolean>;
export declare const resumePeriodicHandler: (host: PeriodicReplicationHost, processor: PeriodicProcessor) => Promise<boolean>;
export declare function usePeriodicReplication(host: PeriodicReplicationHost): {
disablePeriodic: () => Promise<boolean>;
resumePeriodic: () => Promise<boolean>;
};

View File

@@ -0,0 +1,5 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import type { NecessaryServices } from "@lib/interfaces/ServiceModule.ts";
export type ReplicatorFeatureHost = NecessaryServices<"API" | "replication" | "replicator", never>;
export declare function registerReplicatorCommands(host: ReplicatorFeatureHost): void;

View File

@@ -0,0 +1,4 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
export { useReplicator } from "./replicator";
export { useCouchDBReplicatorFactory, useMinIOReplicatorFactory } from "./replicatorFactories";

View File

@@ -0,0 +1,50 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type AnyEntry, type EntryDoc, type LoadedEntry, type MetaEntry } from "@lib/common/types";
import { Semaphore } from "octagonal-wheels/concurrency/semaphore_v2";
import type { ReactiveSource } from "octagonal-wheels/dataobject/reactive_v2";
import type { NecessaryObsidianFeature } from "@/types";
import { type LogFunction } from "@lib/services/lib/logUtils";
export declare const KV_KEY_REPLICATION_RESULT_PROCESSOR_SNAPSHOT = "replicationResultProcessorSnapshot";
export type ReplicateResultProcessorHost = NecessaryObsidianFeature<"API" | "appLifecycle" | "database" | "keyValueDB" | "path" | "replication" | "replicator" | "setting" | "vault">;
export type ReplicateResultProcessorSnapshot = {
queued: PouchDB.Core.ExistingDocument<EntryDoc>[];
processing: PouchDB.Core.ExistingDocument<EntryDoc>[];
};
export type ReplicateResultProcessorState = {
queuedChanges: PouchDB.Core.ExistingDocument<EntryDoc>[];
processingChanges: PouchDB.Core.ExistingDocument<EntryDoc>[];
suspended: boolean;
restoreFromSnapshot: Promise<void> | undefined;
semaphore: ReturnType<typeof Semaphore>;
isRunningProcessQueue: boolean;
triggerTakeSnapshot: () => void;
};
export type ReplicateResultProcessor = {
suspend: () => void;
resume: () => void;
enqueueAll: (changes: PouchDB.Core.ExistingDocument<EntryDoc>[]) => void;
restoreFromSnapshotOnce: () => Promise<void>;
};
type ReplicateResultProcessorLog = LogFunction;
export declare function createReplicateResultProcessorLog(host: ReplicateResultProcessorHost): ReplicateResultProcessorLog;
export declare function createReplicateResultProcessorState(triggerTakeSnapshot?: () => void): ReplicateResultProcessorState;
export declare function isReplicateResultProcessorSuspended(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState): boolean;
export declare function suspendReplicateResultProcessing(state: ReplicateResultProcessorState): void;
export declare function resumeReplicateResultProcessing(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState, log?: ReplicateResultProcessorLog): void;
export declare function takeReplicateResultProcessorSnapshot(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState, log?: ReplicateResultProcessorLog): Promise<void>;
export declare function restoreReplicateResultProcessorSnapshot(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState, log?: ReplicateResultProcessorLog): Promise<void>;
export declare function restoreReplicateResultProcessorSnapshotOnce(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState, log?: ReplicateResultProcessorLog): Promise<void>;
export declare function withCounting<T>(proc: () => Promise<T>, countValue: ReactiveSource<number>): Promise<T>;
export declare function reportReplicateResultProcessorStatus(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState): void;
export declare function enqueueAllReplicateResults(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState, log: ReplicateResultProcessorLog, changes: PouchDB.Core.ExistingDocument<EntryDoc>[]): void;
export declare function processIfNonDocumentChange(host: ReplicateResultProcessorHost, log: ReplicateResultProcessorLog, change: PouchDB.Core.ExistingDocument<EntryDoc>): boolean;
export declare function enqueueReplicateResult(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState, log: ReplicateResultProcessorLog, doc: PouchDB.Core.ExistingDocument<EntryDoc>): void;
export declare function runReplicateResultProcessQueue(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState, log?: ReplicateResultProcessorLog): Promise<void>;
export declare function parseReplicateResultDocumentChange(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState, log: ReplicateResultProcessorLog, change: PouchDB.Core.ExistingDocument<EntryDoc>): Promise<void>;
export declare function applyReplicateResultToDatabase(host: ReplicateResultProcessorHost, state: ReplicateResultProcessorState, log: ReplicateResultProcessorLog, doc: PouchDB.Core.ExistingDocument<AnyEntry>): Promise<void>;
export declare function applyReplicateResultToDatabaseInternal(host: ReplicateResultProcessorHost, log: ReplicateResultProcessorLog, doc_: PouchDB.Core.ExistingDocument<AnyEntry>): Promise<void>;
export declare function applyReplicateResultToStorage(host: ReplicateResultProcessorHost, entry: MetaEntry): Promise<void>;
export declare function checkIsChangeRequiredForDatabaseProcessing(host: ReplicateResultProcessorHost, log: ReplicateResultProcessorLog, dbDoc: LoadedEntry): Promise<boolean>;
export declare function useReplicateResultProcessor(host: ReplicateResultProcessorHost): ReplicateResultProcessor;
export {};

View File

@@ -0,0 +1,16 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type EntryDoc } from "@lib/common/types";
import { type ReplicateResultProcessor } from "./replicateResultProcessor";
import { UnresolvedErrorManager } from "@lib/services/base/UnresolvedErrorManager";
import { type LogFunction } from "@lib/services/lib/logUtils";
import type { NecessaryObsidianFeature } from "@/types";
export type ReplicatorHost = NecessaryObsidianFeature<"appLifecycle" | "replication" | "replicator" | "setting" | "tweakValue" | "API" | "database" | "databaseEvents" | "keyValueDB" | "path" | "vault" | "UI", "databaseFileAccess" | "rebuilder">;
export declare const everyOnloadAfterLoadSettingsHandler: (host: ReplicatorHost, processor: ReplicateResultProcessor) => Promise<boolean>;
export declare const onReplicatorInitialisedHandler: () => Promise<boolean>;
export declare const everyOnDatabaseInitializedHandler: (processor: ReplicateResultProcessor, showNotice: boolean) => Promise<boolean>;
export declare const everyBeforeReplicateHandler: (unresolvedErrorManager: UnresolvedErrorManager, processor: ReplicateResultProcessor, showMessage: boolean) => Promise<boolean>;
export declare const cleanedHandler: (host: ReplicatorHost, showMessage: boolean, log?: LogFunction) => Promise<void>;
export declare const onReplicationFailedHandler: (host: ReplicatorHost, showMessage?: boolean, log?: LogFunction) => Promise<boolean>;
export declare const parseReplicationResultHandler: (processor: ReplicateResultProcessor, docs: Array<PouchDB.Core.ExistingDocument<EntryDoc>>) => Promise<boolean>;
export declare function useReplicator(host: ReplicatorHost): void;

View File

@@ -0,0 +1,13 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type RemoteDBSettings } from "@lib/common/types";
import type { LiveSyncAbstractReplicator } from "@lib/replication/LiveSyncAbstractReplicator";
import type { NecessaryObsidianFeature } from "@/types";
type CouchDBReplicatorHost = NecessaryObsidianFeature<"replicator" | "appLifecycle" | "replication" | "setting">;
export declare const createCouchDBReplicatorHandler: (host: CouchDBReplicatorHost, settingOverride?: Partial<RemoteDBSettings>) => Promise<LiveSyncAbstractReplicator | false>;
export declare const resumeCouchDBReplicationHandler: (host: CouchDBReplicatorHost) => Promise<boolean>;
export declare function useCouchDBReplicatorFactory(host: CouchDBReplicatorHost): void;
type MinIOReplicatorHost = NecessaryObsidianFeature<"replicator" | "setting">;
export declare const createMinIOReplicatorHandler: (host: MinIOReplicatorHost, settingOverride?: Partial<RemoteDBSettings>) => Promise<LiveSyncAbstractReplicator | false>;
export declare function useMinIOReplicatorFactory(host: MinIOReplicatorHost): void;
export {};

View File

@@ -0,0 +1,27 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { type ObsidianLiveSyncSettings } from "@lib/common/types.ts";
export declare const enum UserMode {
NewUser = "new-user",
ExistingUser = "existing-user",
Unknown = "unknown",
Update = "unknown" // eslint-disable-line @typescript-eslint/no-duplicate-enum-values -- Duplicate enum value
}
export interface SetupManagerAPI {
startOnBoarding(): Promise<boolean>;
onOnboard(userMode: UserMode): Promise<boolean>;
onUseSetupURI(userMode: UserMode, setupURI?: string): Promise<boolean>;
onCouchDBManualSetup(userMode: UserMode, currentSetting: ObsidianLiveSyncSettings, activate?: boolean): Promise<boolean>;
onBucketManualSetup(userMode: UserMode, currentSetting: ObsidianLiveSyncSettings, activate?: boolean): Promise<boolean>;
onP2PManualSetup(userMode: UserMode, currentSetting: ObsidianLiveSyncSettings, activate?: boolean): Promise<boolean>;
onlyE2EEConfiguration(userMode: UserMode, currentSetting: ObsidianLiveSyncSettings): Promise<boolean>;
onConfigureManually(originalSetting: ObsidianLiveSyncSettings, userMode: UserMode): Promise<boolean>;
onSelectServer(currentSetting: ObsidianLiveSyncSettings, userMode: UserMode): Promise<boolean>;
onConfirmApplySettingsFromWizard(newConf: ObsidianLiveSyncSettings, _userMode: UserMode, activate?: boolean, extra?: () => void): Promise<boolean>;
onPromptQRCodeInstruction(): Promise<boolean>;
decodeQR(qr: string): Promise<boolean>;
applySetting(newConf: ObsidianLiveSyncSettings, userMode: UserMode): Promise<boolean>;
dialogManager: any; // eslint-disable-line @typescript-eslint/no-explicit-any -- Only type declaration
}
export declare const getSetupManager: () => SetupManagerAPI;
export declare const useSetupManagerFeature: import("@/types.ts").ObsidianServiceFeatureFunction<"setting" | "UI" | "appLifecycle" | "API" | "replicator", "rebuilder", never, SetupManagerAPI>;

View File

@@ -0,0 +1,3 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
export { useMismatchedTweaksResolver } from "./mismatchedTweaksResolver";

View File

@@ -0,0 +1,32 @@
// @ts-nocheck
// REPO: https://github.com/vrtmrz/livesync-commonlib Commit hash: 0563f26
import { TweakValuesShouldMatchedTemplate, type TweakValues, type ObsidianLiveSyncSettings, type RemoteDBSettings } from "@lib/common/types.ts";
import type { NecessaryObsidianFeature } from "@/types";
import { type LogFunction } from "@lib/services/lib/logUtils";
export type MismatchedTweaksResolverHost = NecessaryObsidianFeature<"API" | "setting" | "tweakValue" | "replication" | "replicator" | "UI", "rebuilder">;
export declare function valueToString(value: string | number | boolean | object | undefined): string;
export declare const collectMismatchedTweakKeys: (current: TweakValues, preferred: Partial<TweakValues>) => ("liveSync" | "syncOnSave" | "syncOnStart" | "syncOnFileOpen" | "syncOnEditorSave" | "keepReplicationActiveInBackground" | "syncMinimumInterval" | "showVerboseLog" | "lessInformationInLog" | "showLongerLogInsideEditor" | "showStatusOnEditor" | "showStatusOnStatusbar" | "showOnlyIconsOnEditor" | "hideFileWarningNotice" | "networkWarningStyle" | "displayLanguage" | "trashInsteadDelete" | "doNotDeleteFolder" | "batchSave" | "batchSaveMinimumDelay" | "batchSaveMaximumDelay" | "syncMaxSizeInMB" | "useIgnoreFiles" | "ignoreFiles" | "processSizeMismatchedFiles" | "syncOnlyRegEx" | "syncIgnoreRegEx" | "syncAfterMerge" | "resolveConflictsByNewerFile" | "writeDocumentsIfConflicted" | "disableMarkdownAutoMerge" | "configPassphraseStore" | "encryptedPassphrase" | "encryptedCouchDBConnection" | "periodicReplication" | "periodicReplicationInterval" | "syncInternalFiles" | "syncInternalFilesBeforeReplication" | "syncInternalFilesInterval" | "syncInternalFilesIgnorePatterns" | "syncInternalFilesTargetPatterns" | "watchInternalFileChanges" | "suppressNotifyHiddenFilesChange" | "syncInternalFileOverwritePatterns" | "usePluginSync" | "usePluginSettings" | "showOwnPlugins" | "autoSweepPlugins" | "autoSweepPluginsPeriodic" | "notifyPluginOrSettingUpdated" | "deviceAndVaultName" | "usePluginSyncV2" | "usePluginEtc" | "pluginSyncExtendedSetting" | "useAdvancedMode" | "usePowerUserMode" | "useEdgeCaseMode" | "notifyThresholdOfRemoteStorageSize" | "disableWorkerForGeneratingChunks" | "processSmallFilesInUIThread" | "savingDelay" | "gcDelay" | "skipOlderFilesOnSync" | "useIndexedDBAdapter" | "enableDebugTools" | "writeLogToTheFile" | "settingSyncFile" | "writeCredentialsForSettingSync" | "notifyAllSettingSyncFile" | "suspendFileWatching" | "suspendParseReplicationResult" | "doNotSuspendOnFetching" | "maxMTimeForReflectEvents" | "versionUpFlash" | "settingVersion" | "isConfigured" | "lastReadUpdates" | "doctorProcessedVersion" | "remoteConfigurations" | "activeConfigurationId" | "P2P_ActiveRemoteConfigurationId" | "couchDB_URI" | "couchDB_USER" | "couchDB_PASSWORD" | "couchDB_DBNAME" | "couchDB_CustomHeaders" | "useJWT" | "jwtAlgorithm" | "jwtKey" | "jwtKid" | "jwtSub" | "jwtExpDuration" | "useRequestAPI" | "accessKey" | "secretKey" | "bucket" | "region" | "endpoint" | "useCustomRequestHandler" | "bucketCustomHeaders" | "bucketPrefix" | "forcePathStyle" | "remoteType" | "encrypt" | "passphrase" | "usePathObfuscation" | "E2EEAlgorithm" | "hashAlg" | "minimumChunkSize" | "customChunkSize" | "longLineThreshold" | "useSegmenter" | "enableChunkSplitterV2" | "doNotUseFixedRevisionForChunks" | "chunkSplitterVersion" | "useEden" | "maxChunksInEden" | "maxTotalLengthInEden" | "maxAgeInEden" | "tweakModified" | "checkIntegrityOnSave" | "useHistory" | "disableRequestURI" | "sendChunksBulk" | "sendChunksBulkMaxSize" | "useDynamicIterationCount" | "doNotPaceReplication" | "readChunksOnline" | "useOnlyLocalChunk" | "concurrencyOfReadChunksOnline" | "minimumIntervalOfReadChunksOnline" | "enableCompression" | "batch_size" | "batches_limit" | "ignoreVersionCheck" | "disableCheckingConfigMismatch" | "autoAcceptCompatibleTweak" | "hashCacheMaxCount" | "hashCacheMaxAmount" | "permitEmptyPassphrase" | "handleFilenameCaseSensitive" | "checkConflictOnlyOnOpen" | "showMergeDialogOnlyOnActive" | "additionalSuffixOfDatabaseName" | "useTimeouts" | "deleteMetadataOfDeletedFiles" | "automaticallyDeleteMetadataOfDeletedFiles" | "P2P_AutoAccepting" | "P2P_AutoSyncPeers" | "P2P_AutoWatchPeers" | "P2P_SyncOnReplication" | "P2P_RebuildFrom" | "P2P_AutoAcceptingPeers" | "P2P_AutoDenyingPeers" | "P2P_IsHeadless" | "P2P_Enabled" | "P2P_relays" | "P2P_roomID" | "P2P_passphrase" | "P2P_AppID" | "P2P_AutoStart" | "P2P_AutoBroadcast" | "P2P_DevicePeerName" | "P2P_turnServers" | "P2P_turnUsername" | "P2P_turnCredential" | "P2P_useDiagRTC")[];
export declare const selectNewerTweakSide: (current: TweakValues, preferred: Partial<TweakValues>, log?: LogFunction) => "REMOTE" | "CURRENT";
export declare const shouldAutoAcceptCompatibleLossy: (host: MismatchedTweaksResolverHost, state: {
hasNotifiedAutoAcceptCompatibleUndefined: boolean;
}, current: TweakValues, preferred: Partial<TweakValues>, mismatchedKeys: (keyof typeof TweakValuesShouldMatchedTemplate)[]) => Promise<"REMOTE" | "CURRENT" | undefined>;
export declare const onBeforeSaveSettingDataHandler: (next: ObsidianLiveSyncSettings, previous: ObsidianLiveSyncSettings, log?: LogFunction) => Promise<{
tweakModified: number;
} | undefined>;
export declare const anyAfterConnectCheckFailedHandler: (host: MismatchedTweaksResolverHost) => Promise<boolean | "CHECKAGAIN" | undefined>;
export declare const checkAndAskResolvingMismatchedTweaksHandler: (host: MismatchedTweaksResolverHost, state: {
hasNotifiedAutoAcceptCompatibleUndefined: boolean;
}, preferred: TweakValues) => Promise<[TweakValues | boolean, boolean]>;
export declare const askResolvingMismatchedTweaksHandler: (host: MismatchedTweaksResolverHost) => Promise<"OK" | "CHECKAGAIN" | "IGNORE">;
export declare const fetchRemotePreferredTweakValuesHandler: (host: MismatchedTweaksResolverHost, trialSetting: RemoteDBSettings) => Promise<TweakValues | false>;
export declare const checkAndAskUseRemoteConfigurationHandler: (host: MismatchedTweaksResolverHost, trialSetting: RemoteDBSettings) => Promise<{
result: false | TweakValues;
requireFetch: boolean;
}>;
export declare const askUseRemoteConfigurationHandler: (host: MismatchedTweaksResolverHost, state: {
hasNotifiedAutoAcceptCompatibleUndefined: boolean;
}, trialSetting: RemoteDBSettings, preferred: TweakValues) => Promise<{
result: false | TweakValues;
requireFetch: boolean;
}>;
export declare function useMismatchedTweaksResolver(host: MismatchedTweaksResolverHost): void;

26
_types/src/types.d.ts vendored
View File

@@ -5,6 +5,10 @@ import type { Rebuilder } from "@lib/interfaces/DatabaseRebuilder";
import type { IFileHandler } from "@lib/interfaces/FileHandler";
import type { StorageAccess } from "@lib/interfaces/StorageAccess";
import type { IServiceHub } from "@lib/services/base/IService";
import type { LiveSyncBaseCore } from "./LiveSyncBaseCore.ts";
import type { ObsidianServiceContext } from "@lib/services/implements/obsidian/ObsidianServiceContext.ts";
import type { LiveSyncCommands } from "./features/LiveSyncCommands.ts";
import type { ObsidianServiceHub } from "./modules/services/ObsidianServiceHub.ts";
export interface ServiceModules {
storageAccess: StorageAccess;
/**
@@ -24,3 +28,25 @@ export interface LiveSyncHost {
services: IServiceHub;
serviceModules: ServiceModules;
}
export type LiveSyncCore = LiveSyncBaseCore<ObsidianServiceContext, LiveSyncCommands>;
/**
* Extends the standard `{ services, serviceModules }` host shape with a typed
* `context` slice from `ObsidianServiceContext`.
*
* Use this as the host type for features built with `createServiceFeature` that
* also need type-safe access to Obsidian-specific context properties such as
* `app` or `plugin`.
*
* @typeParam T - Service keys (same constraint as `NecessaryObsidianFeature`).
* @typeParam U - Service module keys from `ServiceModules`.
* @typeParam C - Keys of `ObsidianServiceContext` to expose (e.g. `"app" | "plugin"`).
*/
export type NecessaryObsidianFeature<T extends keyof ObsidianServiceHub, U extends keyof ServiceModules = never, C extends keyof ObsidianServiceContext = never> = {
services: Pick<ObsidianServiceHub, T>;
serviceModules: Pick<ServiceModules, U>;
context: Pick<ObsidianServiceContext, C>;
};
/** Alias to keep backward compatibility with defined feature hosts */
export type NecessaryObsidianServices<T extends keyof ObsidianServiceHub, U extends keyof ServiceModules = never, C extends keyof ObsidianServiceContext = never> = NecessaryObsidianFeature<T, U, C>;
export type ObsidianServiceFeatureFunction<T extends keyof ObsidianServiceHub, U extends keyof ServiceModules, C extends keyof ObsidianServiceContext, TR> = (host: NecessaryObsidianFeature<T, U, C>) => TR;
export declare function createObsidianServiceFeature<T extends keyof ObsidianServiceHub, U extends keyof ServiceModules = never, C extends keyof ObsidianServiceContext = never, TR = void>(featureFunction: ObsidianServiceFeatureFunction<T, U, C, TR>): ObsidianServiceFeatureFunction<T, U, C, TR>;

57
devs.md
View File

@@ -116,6 +116,7 @@ The plugin uses a dynamic module system to reduce coupling and improve maintaina
- **Services**: Core services (e.g., `database`, `replicator`, `storageAccess`) are registered in `ServiceHub` and accessed by modules. They provide an extension point for add new behaviour without modifying existing code.
- For example, checks before the replication can be added to the `replication.onBeforeReplicate` handler, and the handlers can be return `false` to prevent replication-starting. `vault.isTargetFile` also can be used to prevent processing specific files.
- **ServiceModule**: A new type of module that directly depends on services.
- **serviceFeature**: A decoupled functional feature (defined via `createServiceFeature` or `createObsidianServiceFeature`) that encapsulates state and behaviour within its function closure. Unlike legacy modules, it does not register itself onto the `ServiceHub` registry, preventing global namespace pollution, and enabling simple unit testing.
#### Note on Module vs Service
@@ -176,18 +177,56 @@ Hence, the new feature should be implemented as follows:
## Common Patterns
### Module Implementation (Now not recommended for new features, use services instead)
### Service Feature Implementation (Highly Recommended for New Features and UI/Event Registrars)
Instead of subclassing 'AbstractModule' or 'AbstractObsidianModule', features should be implemented as functional closures.
#### Standard Service Feature
Use `createServiceFeature` for features that do not depend on the Obsidian application context:
```typescript
export class ModuleExample extends AbstractObsidianModule {
async _everyOnloadStart(): Promise<boolean> {
/* ... */
}
import { createServiceFeature } from "@lib/interfaces/ServiceModule.ts";
onBindFunction(core: LiveSyncCore, services: typeof core.services): void {
services.appLifecycle.handleOnInitialise(this._everyOnloadStart.bind(this));
}
}
export const useMyFeature = createServiceFeature(({ services, serviceModules }) => {
// Encapsulated state in the function closure
let localCache = "";
const onInitialise = (): Promise<boolean> => {
services.setting.saveSettingData();
return Promise.resolve(true);
};
services.appLifecycle.onInitialise.addHandler(onInitialise);
});
```
#### Obsidian-Specific Service Feature
Use `createObsidianServiceFeature` for features requiring Obsidian context (`app`, `plugin`, or `liveSyncPlugin`):
```typescript
import { createObsidianServiceFeature } from "@/types.ts";
export const useMyObsidianFeature = createObsidianServiceFeature<
MyFeatureServices,
MyFeatureModules,
"app" | "liveSyncPlugin"
>((host) => {
const plugin = host.context.liveSyncPlugin;
const onLayoutReady = (): Promise<boolean> => {
host.services.API.addCommand({
id: "my-command",
name: "My plug-in command",
callback: () => {
// Access typed context safely
console.log(host.context.app.vault.getName());
}
});
return Promise.resolve(true);
};
host.services.appLifecycle.onLayoutReady.addHandler(onLayoutReady);
});
```
### Settings Management

Some files were not shown because too many files have changed in this diff Show More