mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-10-25 18:43:20 +00:00
chore: ran prettier
This commit is contained in:
11 files changed
+52
-28
No files matched your search
@@ -39,7 +39,8 @@ export class LiveSyncBaseCore<
|
|||||||
LiveSyncReplicatorEnv,
|
LiveSyncReplicatorEnv,
|
||||||
LiveSyncJournalReplicatorEnv,
|
LiveSyncJournalReplicatorEnv,
|
||||||
LiveSyncCouchDBReplicatorEnv,
|
LiveSyncCouchDBReplicatorEnv,
|
||||||
HasSettings<ObsidianLiveSyncSettings> {
|
HasSettings<ObsidianLiveSyncSettings>
|
||||||
|
{
|
||||||
addOns = [] as TCommands[];
|
addOns = [] as TCommands[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -43,10 +43,13 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext
|
|||||||
|
|
||||||
// 3. Re-enable sync.
|
// 3. Re-enable sync.
|
||||||
const restoreSyncSettings = async () => {
|
const restoreSyncSettings = async () => {
|
||||||
await core.services.setting.applyPartial({
|
await core.services.setting.applyPartial(
|
||||||
|
{
|
||||||
...context.originalSyncSettings,
|
...context.originalSyncSettings,
|
||||||
suspendFileWatching: false,
|
suspendFileWatching: false,
|
||||||
}, true);
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
// applySettings fires the full lifecycle: onSuspending → onResumed.
|
// applySettings fires the full lifecycle: onSuspending → onResumed.
|
||||||
// ModuleReplicatorCouchDB starts continuous replication on onResumed
|
// ModuleReplicatorCouchDB starts continuous replication on onResumed
|
||||||
// via fireAndForget.
|
// via fireAndForget.
|
||||||
@@ -54,10 +57,13 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext
|
|||||||
// Lifecycle events (onSuspending) may re-enable suspension flags.
|
// Lifecycle events (onSuspending) may re-enable suspension flags.
|
||||||
// Clear them explicitly after the lifecycle completes. applyPartial
|
// Clear them explicitly after the lifecycle completes. applyPartial
|
||||||
// with true is a direct store write — it does not re-trigger lifecycle.
|
// with true is a direct store write — it does not re-trigger lifecycle.
|
||||||
await core.services.setting.applyPartial({
|
await core.services.setting.applyPartial(
|
||||||
|
{
|
||||||
suspendFileWatching: false,
|
suspendFileWatching: false,
|
||||||
suspendParseReplicationResult: false,
|
suspendParseReplicationResult: false,
|
||||||
}, true);
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
};
|
};
|
||||||
if (options.interval) {
|
if (options.interval) {
|
||||||
log(`Polling mode: syncing every ${options.interval}s`);
|
log(`Polling mode: syncing every ${options.interval}s`);
|
||||||
@@ -80,7 +86,9 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext
|
|||||||
currentIntervalMs = Math.min(baseIntervalMs * Math.pow(2, consecutiveFailures), maxIntervalMs);
|
currentIntervalMs = Math.min(baseIntervalMs * Math.pow(2, consecutiveFailures), maxIntervalMs);
|
||||||
console.error(`[Daemon] Poll error (${consecutiveFailures} consecutive):`, err);
|
console.error(`[Daemon] Poll error (${consecutiveFailures} consecutive):`, err);
|
||||||
if (consecutiveFailures >= 5) {
|
if (consecutiveFailures >= 5) {
|
||||||
console.error(`[Daemon] Warning: ${consecutiveFailures} consecutive failures, backing off to ${Math.round(currentIntervalMs / 1000)}s`);
|
console.error(
|
||||||
|
`[Daemon] Warning: ${consecutiveFailures} consecutive failures, backing off to ${Math.round(currentIntervalMs / 1000)}s`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pollTimer = setTimeout(poll, currentIntervalMs);
|
pollTimer = setTimeout(poll, currentIntervalMs);
|
||||||
@@ -99,9 +107,11 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext
|
|||||||
log("LiveSync active");
|
log("LiveSync active");
|
||||||
const currentSettings = core.services.setting.currentSettings();
|
const currentSettings = core.services.setting.currentSettings();
|
||||||
if (!currentSettings.liveSync && !currentSettings.syncOnStart) {
|
if (!currentSettings.liveSync && !currentSettings.syncOnStart) {
|
||||||
console.error("[Daemon] Warning: liveSync and syncOnStart are both disabled in settings. " +
|
console.error(
|
||||||
|
"[Daemon] Warning: liveSync and syncOnStart are both disabled in settings. " +
|
||||||
"No sync will occur. Set liveSync=true in your settings file for continuous sync, " +
|
"No sync will occur. Set liveSync=true in your settings file for continuous sync, " +
|
||||||
"or use --interval for polling mode.");
|
"or use --interval for polling mode."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,16 @@ export interface CLICommandContext {
|
|||||||
databasePath: string;
|
databasePath: string;
|
||||||
core: LiveSyncBaseCore<ServiceContext, any>;
|
core: LiveSyncBaseCore<ServiceContext, any>;
|
||||||
settingsPath: string;
|
settingsPath: string;
|
||||||
originalSyncSettings: Pick<ObsidianLiveSyncSettings, "liveSync" | "syncOnStart" | "periodicReplication" | "syncOnSave" | "syncOnEditorSave" | "syncOnFileOpen" | "syncAfterMerge">;
|
originalSyncSettings: Pick<
|
||||||
|
ObsidianLiveSyncSettings,
|
||||||
|
| "liveSync"
|
||||||
|
| "syncOnStart"
|
||||||
|
| "periodicReplication"
|
||||||
|
| "syncOnSave"
|
||||||
|
| "syncOnEditorSave"
|
||||||
|
| "syncOnFileOpen"
|
||||||
|
| "syncAfterMerge"
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const VALID_COMMANDS = new Set([
|
export const VALID_COMMANDS = new Set([
|
||||||
|
|||||||
@@ -280,16 +280,13 @@ export async function main() {
|
|||||||
// chokidar's ignored option is populated when beginWatch() fires during onLoad().
|
// chokidar's ignored option is populated when beginWatch() fires during onLoad().
|
||||||
const watchEnabled = options.command === "daemon";
|
const watchEnabled = options.command === "daemon";
|
||||||
const vaultPath =
|
const vaultPath =
|
||||||
options.command === "mirror" && options.commandArgs[0]
|
options.command === "mirror" && options.commandArgs[0] ? path.resolve(options.commandArgs[0]) : databasePath;
|
||||||
? path.resolve(options.commandArgs[0])
|
|
||||||
: databasePath;
|
|
||||||
let ignoreRules: IgnoreRules | undefined;
|
let ignoreRules: IgnoreRules | undefined;
|
||||||
if (options.command === "daemon" || options.command === "mirror") {
|
if (options.command === "daemon" || options.command === "mirror") {
|
||||||
ignoreRules = new IgnoreRules(vaultPath);
|
ignoreRules = new IgnoreRules(vaultPath);
|
||||||
await ignoreRules.load();
|
await ignoreRules.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create service context and hub
|
// Create service context and hub
|
||||||
const context = new NodeServiceContext(databasePath);
|
const context = new NodeServiceContext(databasePath);
|
||||||
const serviceHubInstance = new NodeServiceHub<NodeServiceContext>(databasePath, context);
|
const serviceHubInstance = new NodeServiceHub<NodeServiceContext>(databasePath, context);
|
||||||
|
|||||||
@@ -97,7 +97,11 @@ class CLIConverterAdapter implements IStorageEventConverterAdapter<NodeFile> {
|
|||||||
class CLIWatchAdapter implements IStorageEventWatchAdapter {
|
class CLIWatchAdapter implements IStorageEventWatchAdapter {
|
||||||
private _watcher: FSWatcher | undefined;
|
private _watcher: FSWatcher | undefined;
|
||||||
|
|
||||||
constructor(private basePath: string, private ignoreRules?: IgnoreRules, private watchEnabled: boolean = false) {}
|
constructor(
|
||||||
|
private basePath: string,
|
||||||
|
private ignoreRules?: IgnoreRules,
|
||||||
|
private watchEnabled: boolean = false
|
||||||
|
) {}
|
||||||
|
|
||||||
private _toNodeFile(filePath: string, stats: Stats | undefined): NodeFile {
|
private _toNodeFile(filePath: string, stats: Stats | undefined): NodeFile {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -60,10 +60,7 @@ describe("CLIStorageEventManagerAdapter", () => {
|
|||||||
await adapter.watch.beginWatch(handlers);
|
await adapter.watch.beginWatch(handlers);
|
||||||
|
|
||||||
expect(chokidar.watch).toHaveBeenCalledTimes(1);
|
expect(chokidar.watch).toHaveBeenCalledTimes(1);
|
||||||
expect(chokidar.watch).toHaveBeenCalledWith(
|
expect(chokidar.watch).toHaveBeenCalledWith("/base", expect.objectContaining({ ignoreInitial: true }));
|
||||||
"/base",
|
|
||||||
expect.objectContaining({ ignoreInitial: true })
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("add event produces NodeFile with correct relative path via onCreate", async () => {
|
it("add event produces NodeFile with correct relative path via onCreate", async () => {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export function initialiseServiceModulesCLI(
|
|||||||
core: LiveSyncBaseCore<ServiceContext, any>,
|
core: LiveSyncBaseCore<ServiceContext, any>,
|
||||||
services: InjectableServiceHub<ServiceContext>,
|
services: InjectableServiceHub<ServiceContext>,
|
||||||
ignoreRules?: IgnoreRules,
|
ignoreRules?: IgnoreRules,
|
||||||
watchEnabled: boolean = false,
|
watchEnabled: boolean = false
|
||||||
): ServiceModules {
|
): ServiceModules {
|
||||||
const storageAccessManager = new StorageAccessManager();
|
const storageAccessManager = new StorageAccessManager();
|
||||||
|
|
||||||
@@ -39,13 +39,19 @@ export function initialiseServiceModulesCLI(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// CLI-specific storage event manager
|
// CLI-specific storage event manager
|
||||||
const storageEventManager = new StorageEventManagerCLI(basePath, core, {
|
const storageEventManager = new StorageEventManagerCLI(
|
||||||
|
basePath,
|
||||||
|
core,
|
||||||
|
{
|
||||||
fileProcessing: services.fileProcessing,
|
fileProcessing: services.fileProcessing,
|
||||||
setting: services.setting,
|
setting: services.setting,
|
||||||
vaultService: services.vault,
|
vaultService: services.vault,
|
||||||
storageAccessManager: storageAccessManager,
|
storageAccessManager: storageAccessManager,
|
||||||
APIService: services.API,
|
APIService: services.API,
|
||||||
}, ignoreRules, watchEnabled);
|
},
|
||||||
|
ignoreRules,
|
||||||
|
watchEnabled
|
||||||
|
);
|
||||||
|
|
||||||
// Close the file watcher during graceful shutdown so the process can exit cleanly.
|
// Close the file watcher during graceful shutdown so the process can exit cleanly.
|
||||||
services.appLifecycle.onUnload.addHandler(async () => {
|
services.appLifecycle.onUnload.addHandler(async () => {
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ export class IgnoreRules {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (trimmed.startsWith("import:")) {
|
if (trimmed.startsWith("import:")) {
|
||||||
console.error(`[IgnoreRules] Warning: unrecognised directive '${trimmed}' — only 'import: .gitignore' is supported`);
|
console.error(
|
||||||
|
`[IgnoreRules] Warning: unrecognised directive '${trimmed}' — only 'import: .gitignore' is supported`
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this._addPattern(trimmed);
|
this._addPattern(trimmed);
|
||||||
|
|||||||
@@ -122,10 +122,7 @@ describe("IgnoreRules", () => {
|
|||||||
describe("load() with comments and blank lines", () => {
|
describe("load() with comments and blank lines", () => {
|
||||||
it("skips # comment lines and blank lines", async () => {
|
it("skips # comment lines and blank lines", async () => {
|
||||||
const vaultPath = await createVault();
|
const vaultPath = await createVault();
|
||||||
await writeIgnoreFile(
|
await writeIgnoreFile(vaultPath, "# This is a comment\n\n \n*.tmp\n# another comment\nbuild/\n");
|
||||||
vaultPath,
|
|
||||||
"# This is a comment\n\n \n*.tmp\n# another comment\nbuild/\n"
|
|
||||||
);
|
|
||||||
const rules = new IgnoreRules(vaultPath);
|
const rules = new IgnoreRules(vaultPath);
|
||||||
await rules.load();
|
await rules.load();
|
||||||
expect(rules.shouldIgnore("scratch.tmp")).toBe(true);
|
expect(rules.shouldIgnore("scratch.tmp")).toBe(true);
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ function injectBanner(): import("vite").Plugin {
|
|||||||
// Insert after the shebang line if present, otherwise at the top.
|
// Insert after the shebang line if present, otherwise at the top.
|
||||||
if (chunk.code.startsWith("#!")) {
|
if (chunk.code.startsWith("#!")) {
|
||||||
const newline = chunk.code.indexOf("\n");
|
const newline = chunk.code.indexOf("\n");
|
||||||
chunk.code = chunk.code.slice(0, newline + 1) + fileReaderPolyfillBanner + chunk.code.slice(newline + 1);
|
chunk.code =
|
||||||
|
chunk.code.slice(0, newline + 1) + fileReaderPolyfillBanner + chunk.code.slice(newline + 1);
|
||||||
} else {
|
} else {
|
||||||
chunk.code = fileReaderPolyfillBanner + chunk.code;
|
chunk.code = fileReaderPolyfillBanner + chunk.code;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type { TFile, App, TFolder } from "obsidian";
|
|||||||
* Vault adapter implementation for Obsidian
|
* Vault adapter implementation for Obsidian
|
||||||
*/
|
*/
|
||||||
export class ObsidianVaultAdapter implements IVaultAdapter<TFile> {
|
export class ObsidianVaultAdapter implements IVaultAdapter<TFile> {
|
||||||
constructor(private app: App) { }
|
constructor(private app: App) {}
|
||||||
|
|
||||||
async read(file: TFile): Promise<string> {
|
async read(file: TFile): Promise<string> {
|
||||||
return await this.app.vault.read(file);
|
return await this.app.vault.read(file);
|
||||||
|
|||||||
Reference in new issue
Block a user