143 lines
3.4 KiB
TypeScript
143 lines
3.4 KiB
TypeScript
import { store } from "$sb/plugos-syscall/mod.ts";
|
|
import {
|
|
editor,
|
|
index,
|
|
space,
|
|
sync,
|
|
system,
|
|
} from "$sb/silverbullet-syscall/mod.ts";
|
|
import type { SyncEndpoint } from "$sb/silverbullet-syscall/sync.ts";
|
|
|
|
export async function configureCommand() {
|
|
const url = await editor.prompt(
|
|
"Enter the URL of the remote space to sync with",
|
|
"https://",
|
|
);
|
|
if (!url) {
|
|
return;
|
|
}
|
|
|
|
const user = await editor.prompt("Username (if any):");
|
|
let password = undefined;
|
|
if (user) {
|
|
password = await editor.prompt("Password:");
|
|
}
|
|
|
|
const syncConfig: SyncEndpoint = {
|
|
url,
|
|
user,
|
|
password,
|
|
};
|
|
|
|
try {
|
|
await system.invokeFunction("server", "check", syncConfig);
|
|
} catch (e: any) {
|
|
await editor.flashNotification(
|
|
`Sync configuration failed: ${e.message}`,
|
|
"error",
|
|
);
|
|
return;
|
|
}
|
|
|
|
await store.batchSet([
|
|
{ key: "sync.config", value: syncConfig },
|
|
// Empty initial snapshot
|
|
{ key: "sync.snapshot", value: {} },
|
|
]);
|
|
|
|
await editor.flashNotification("Sync configuration saved.");
|
|
|
|
return syncConfig;
|
|
}
|
|
|
|
export async function syncCommand() {
|
|
let config: SyncEndpoint | undefined = await store.get("sync.config");
|
|
if (!config) {
|
|
config = await configureCommand();
|
|
if (!config) {
|
|
return;
|
|
}
|
|
}
|
|
await editor.flashNotification("Starting sync...");
|
|
try {
|
|
await system.invokeFunction("server", "check", config);
|
|
|
|
const operations = await system.invokeFunction("server", "performSync");
|
|
await editor.flashNotification(
|
|
`Sync complete. Performed ${operations} operations.`,
|
|
);
|
|
} catch (e: any) {
|
|
await editor.flashNotification(
|
|
`Sync failed: ${e.message}`,
|
|
"error",
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function localWipeAndSyncCommand() {
|
|
let config: SyncEndpoint | undefined = await store.get("sync.config");
|
|
if (!config) {
|
|
config = await configureCommand();
|
|
if (!config) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (
|
|
!(await editor.confirm(
|
|
"Are you sure you want to wipe your local space and sync with the remote?",
|
|
))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
if (
|
|
!(await editor.confirm(
|
|
"To be clear: this means all local content will be deleted with no way to recover it. Are you sure?",
|
|
))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
console.log("Wiping local pages");
|
|
await editor.flashNotification("Now wiping all pages");
|
|
for (const page of await space.listPages()) {
|
|
console.log("Deleting page", page.name);
|
|
await space.deletePage(page.name);
|
|
}
|
|
|
|
console.log("Wiping local attachments");
|
|
await editor.flashNotification("Now wiping all attachments");
|
|
for (const attachment of await space.listAttachments()) {
|
|
console.log("Deleting attachment", attachment.name);
|
|
await space.deleteAttachment(attachment.name);
|
|
}
|
|
|
|
console.log("Wiping local sync state");
|
|
await store.set("sync.snapshot", {});
|
|
|
|
// Starting actual sync
|
|
await syncCommand();
|
|
}
|
|
|
|
// Run on server
|
|
export function check(config: SyncEndpoint) {
|
|
return sync.check(config);
|
|
}
|
|
|
|
// Run on server
|
|
export async function performSync() {
|
|
const config: SyncEndpoint = await store.get("sync.config");
|
|
const snapshot = await store.get("sync.snapshot");
|
|
const { snapshot: newSnapshot, operations, error } = await sync.sync(
|
|
config,
|
|
snapshot,
|
|
);
|
|
await store.set("sync.snapshot", newSnapshot);
|
|
if (error) {
|
|
console.error("Sync error", error);
|
|
throw new Error(error);
|
|
}
|
|
return operations;
|
|
}
|