mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2025-12-13 17:55:56 +00:00
Implemented:
- using Obsidian API to synchronize. - Copy button on history dialog. Documented: - Document improved.
This commit is contained in:
@@ -18,7 +18,14 @@ Note: This password is saved into your Obsidian's vault in plain text.
|
|||||||
The Database name to synchronize.
|
The Database name to synchronize.
|
||||||
⚠️If not exist, created automatically.
|
⚠️If not exist, created automatically.
|
||||||
|
|
||||||
|
|
||||||
|
### Use the old connecting method
|
||||||
|
Since v0.8.0, Self-hosted LiveSync uses Obsidian's API to connect to the CouchDB instead of the browser API.
|
||||||
|
This method will increase the performance and avoid troubles with the CORS.
|
||||||
|
But it doesn't been well tested yet. If you are troubled, please disable this option once.
|
||||||
|
|
||||||
### Test Database connection
|
### Test Database connection
|
||||||
|
You can check the connection by clicking this button.
|
||||||
|
|
||||||
## Local Database Configurations
|
## Local Database Configurations
|
||||||
"Local Database" is created inside your obsidian.
|
"Local Database" is created inside your obsidian.
|
||||||
@@ -44,6 +51,8 @@ As a result, Obsidian's behavior is temporarily slowed down.
|
|||||||
Default is 300 seconds.
|
Default is 300 seconds.
|
||||||
If you are an early adopter, maybe this value is left as 30 seconds. Please change this value to larger values.
|
If you are an early adopter, maybe this value is left as 30 seconds. Please change this value to larger values.
|
||||||
|
|
||||||
|
Note: If you want to use "Use history", this vault must be set to 0.
|
||||||
|
|
||||||
### Manual Garbage Collect
|
### Manual Garbage Collect
|
||||||
Run "Garbage Collection" manually.
|
Run "Garbage Collection" manually.
|
||||||
|
|
||||||
@@ -52,6 +61,8 @@ Encrypt your database. It affects only the database, your files are left as plai
|
|||||||
|
|
||||||
The encryption algorithm is AES-GCM.
|
The encryption algorithm is AES-GCM.
|
||||||
|
|
||||||
|
Note: If you want to use "Plugins and their settings", you have to enable this.
|
||||||
|
|
||||||
### Passphrase
|
### Passphrase
|
||||||
The passphrase to used as the key of encryption. Please use the long text.
|
The passphrase to used as the key of encryption. Please use the long text.
|
||||||
|
|
||||||
@@ -195,6 +206,29 @@ You can set synchronization method at once as these pattern:
|
|||||||
- Sync on File Open : disabled
|
- Sync on File Open : disabled
|
||||||
- Sync on Start : disabled
|
- Sync on Start : disabled
|
||||||
|
|
||||||
|
### Use history
|
||||||
|
If you enable this option, you can keep document histories in your database.
|
||||||
|
(Not all intermediate changes are synchronized.)
|
||||||
|
You can check the changes caused by your edit and/or replication.
|
||||||
|
|
||||||
|
### Enable plugin synchronization
|
||||||
|
If you want to use this feature, you have to activate this feature by this switch.
|
||||||
|
|
||||||
|
### Sweep plugins automatically
|
||||||
|
Plugin sweep will run before replication automatically.
|
||||||
|
|
||||||
|
### Sweep plugins periodically
|
||||||
|
Plugin sweep will run each 1 minute.
|
||||||
|
|
||||||
|
### Notify updates
|
||||||
|
When replication is complete, a message will be notified if a newer version of the plugin applied to this device is configured on another device.
|
||||||
|
|
||||||
|
### Device and Vault name
|
||||||
|
To save the plugins, you have to set a unique name every each device.
|
||||||
|
|
||||||
|
### Open
|
||||||
|
Open the "Plugins and their settings" dialog.
|
||||||
|
|
||||||
## Hatch
|
## Hatch
|
||||||
From here, everything is under the hood. Please handle it with care.
|
From here, everything is under the hood. Please handle it with care.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "obsidian-livesync",
|
"id": "obsidian-livesync",
|
||||||
"name": "Self-hosted LiveSync",
|
"name": "Self-hosted LiveSync",
|
||||||
"version": "0.7.2",
|
"version": "0.8.0",
|
||||||
"minAppVersion": "0.9.12",
|
"minAppVersion": "0.9.12",
|
||||||
"description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
"description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
||||||
"author": "vorotamoroz",
|
"author": "vorotamoroz",
|
||||||
|
|||||||
18
package-lock.json
generated
18
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.7.2",
|
"version": "0.8.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.7.2",
|
"version": "0.8.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"diff-match-patch": "^1.0.5",
|
"diff-match-patch": "^1.0.5",
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-config-airbnb-base": "^14.2.1",
|
"eslint-config-airbnb-base": "^14.2.1",
|
||||||
"eslint-plugin-import": "^2.25.2",
|
"eslint-plugin-import": "^2.25.2",
|
||||||
"obsidian": "^0.13.11",
|
"obsidian": "^0.13.30",
|
||||||
"rollup": "^2.32.1",
|
"rollup": "^2.32.1",
|
||||||
"svelte-preprocess": "^4.10.2",
|
"svelte-preprocess": "^4.10.2",
|
||||||
"tslib": "^2.2.0",
|
"tslib": "^2.2.0",
|
||||||
@@ -2659,9 +2659,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/obsidian": {
|
"node_modules/obsidian": {
|
||||||
"version": "0.13.11",
|
"version": "0.13.30",
|
||||||
"resolved": "https://registry.npmjs.org/obsidian/-/obsidian-0.13.11.tgz",
|
"resolved": "https://registry.npmjs.org/obsidian/-/obsidian-0.13.30.tgz",
|
||||||
"integrity": "sha512-KxOvAh4CG5vzcukmHvyuK9hUIr6ZFlM9FQfGZEwrrEV8VG2/W2Tk5cWrg0VM7EkGE3QBmjX6owjIDIO8QDXVUQ==",
|
"integrity": "sha512-uAOrIyeHE9qYzg1Qjfpy/qlyLUFX9oyKWeHYO8NVDoI+pm5VUTMe7XWcsXPwb9iVsVmggVJcdV15Vqm9bljhxQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/state": "^0.19.6",
|
"@codemirror/state": "^0.19.6",
|
||||||
@@ -5470,9 +5470,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"obsidian": {
|
"obsidian": {
|
||||||
"version": "0.13.11",
|
"version": "0.13.30",
|
||||||
"resolved": "https://registry.npmjs.org/obsidian/-/obsidian-0.13.11.tgz",
|
"resolved": "https://registry.npmjs.org/obsidian/-/obsidian-0.13.30.tgz",
|
||||||
"integrity": "sha512-KxOvAh4CG5vzcukmHvyuK9hUIr6ZFlM9FQfGZEwrrEV8VG2/W2Tk5cWrg0VM7EkGE3QBmjX6owjIDIO8QDXVUQ==",
|
"integrity": "sha512-uAOrIyeHE9qYzg1Qjfpy/qlyLUFX9oyKWeHYO8NVDoI+pm5VUTMe7XWcsXPwb9iVsVmggVJcdV15Vqm9bljhxQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@codemirror/state": "^0.19.6",
|
"@codemirror/state": "^0.19.6",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.7.2",
|
"version": "0.8.0",
|
||||||
"description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
"description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-config-airbnb-base": "^14.2.1",
|
"eslint-config-airbnb-base": "^14.2.1",
|
||||||
"eslint-plugin-import": "^2.25.2",
|
"eslint-plugin-import": "^2.25.2",
|
||||||
"obsidian": "^0.13.11",
|
"obsidian": "^0.13.30",
|
||||||
"rollup": "^2.32.1",
|
"rollup": "^2.32.1",
|
||||||
"tslib": "^2.2.0",
|
"tslib": "^2.2.0",
|
||||||
"typescript": "^4.2.4",
|
"typescript": "^4.2.4",
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { TFile, Modal, App } from "obsidian";
|
|||||||
import { path2id, escapeStringToHTML } from "./utils";
|
import { path2id, escapeStringToHTML } from "./utils";
|
||||||
import ObsidianLiveSyncPlugin from "./main";
|
import ObsidianLiveSyncPlugin from "./main";
|
||||||
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch";
|
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch";
|
||||||
|
import { LOG_LEVEL } from "./types";
|
||||||
|
import { Logger } from "./logger";
|
||||||
|
|
||||||
export class DocumentHistoryModal extends Modal {
|
export class DocumentHistoryModal extends Modal {
|
||||||
plugin: ObsidianLiveSyncPlugin;
|
plugin: ObsidianLiveSyncPlugin;
|
||||||
@@ -14,6 +16,7 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
file: string;
|
file: string;
|
||||||
|
|
||||||
revs_info: PouchDB.Core.RevisionInfo[] = [];
|
revs_info: PouchDB.Core.RevisionInfo[] = [];
|
||||||
|
currentText = "";
|
||||||
|
|
||||||
constructor(app: App, plugin: ObsidianLiveSyncPlugin, file: TFile) {
|
constructor(app: App, plugin: ObsidianLiveSyncPlugin, file: TFile) {
|
||||||
super(app);
|
super(app);
|
||||||
@@ -37,6 +40,7 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
const index = this.revs_info.length - 1 - (this.range.value as any) / 1;
|
const index = this.revs_info.length - 1 - (this.range.value as any) / 1;
|
||||||
const rev = this.revs_info[index];
|
const rev = this.revs_info[index];
|
||||||
const w = await db.getDBEntry(path2id(this.file), { rev: rev.rev }, false, false);
|
const w = await db.getDBEntry(path2id(this.file), { rev: rev.rev }, false, false);
|
||||||
|
this.currentText = "";
|
||||||
|
|
||||||
if (w === false) {
|
if (w === false) {
|
||||||
this.info.innerHTML = "";
|
this.info.innerHTML = "";
|
||||||
@@ -44,6 +48,7 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
} else {
|
} else {
|
||||||
this.info.innerHTML = `Modified:${new Date(w.mtime).toLocaleString()}`;
|
this.info.innerHTML = `Modified:${new Date(w.mtime).toLocaleString()}`;
|
||||||
let result = "";
|
let result = "";
|
||||||
|
this.currentText = w.data;
|
||||||
if (this.showDiff) {
|
if (this.showDiff) {
|
||||||
const prevRevIdx = this.revs_info.length - 1 - ((this.range.value as any) / 1 - 1);
|
const prevRevIdx = this.revs_info.length - 1 - ((this.range.value as any) / 1 - 1);
|
||||||
if (prevRevIdx >= 0 && prevRevIdx < this.revs_info.length) {
|
if (prevRevIdx >= 0 && prevRevIdx < this.revs_info.length) {
|
||||||
@@ -124,6 +129,14 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
this.contentView = div;
|
this.contentView = div;
|
||||||
div.addClass("op-scrollable");
|
div.addClass("op-scrollable");
|
||||||
div.addClass("op-pre");
|
div.addClass("op-pre");
|
||||||
|
const buttons = contentEl.createDiv("");
|
||||||
|
buttons.createEl("button", { text: "Copy to clipboard" }, (e) => {
|
||||||
|
e.addClass("mod-cta");
|
||||||
|
e.addEventListener("click", async () => {
|
||||||
|
await navigator.clipboard.writeText(this.currentText);
|
||||||
|
Logger(`Old content copied to clipboard`, LOG_LEVEL.NOTICE);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
onClose() {
|
onClose() {
|
||||||
const { contentEl } = this;
|
const { contentEl } = this;
|
||||||
|
|||||||
@@ -743,7 +743,7 @@ export class LocalPouchDB {
|
|||||||
username: setting.couchDB_USER,
|
username: setting.couchDB_USER,
|
||||||
password: setting.couchDB_PASSWORD,
|
password: setting.couchDB_PASSWORD,
|
||||||
};
|
};
|
||||||
const dbret = await connectRemoteCouchDB(uri, auth);
|
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
||||||
if (typeof dbret === "string") {
|
if (typeof dbret === "string") {
|
||||||
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
||||||
if (notice != null) notice.hide();
|
if (notice != null) notice.hide();
|
||||||
@@ -820,7 +820,7 @@ export class LocalPouchDB {
|
|||||||
Logger("Another replication running.");
|
Logger("Another replication running.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const dbret = await connectRemoteCouchDB(uri, auth);
|
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
||||||
if (typeof dbret === "string") {
|
if (typeof dbret === "string") {
|
||||||
Logger(`could not connect to ${uri}: ${dbret}`, LOG_LEVEL.NOTICE);
|
Logger(`could not connect to ${uri}: ${dbret}`, LOG_LEVEL.NOTICE);
|
||||||
return false;
|
return false;
|
||||||
@@ -1081,7 +1081,7 @@ export class LocalPouchDB {
|
|||||||
username: setting.couchDB_USER,
|
username: setting.couchDB_USER,
|
||||||
password: setting.couchDB_PASSWORD,
|
password: setting.couchDB_PASSWORD,
|
||||||
};
|
};
|
||||||
const con = await connectRemoteCouchDB(uri, auth);
|
const con = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
||||||
if (typeof con == "string") return;
|
if (typeof con == "string") return;
|
||||||
try {
|
try {
|
||||||
await con.db.destroy();
|
await con.db.destroy();
|
||||||
@@ -1099,7 +1099,7 @@ export class LocalPouchDB {
|
|||||||
username: setting.couchDB_USER,
|
username: setting.couchDB_USER,
|
||||||
password: setting.couchDB_PASSWORD,
|
password: setting.couchDB_PASSWORD,
|
||||||
};
|
};
|
||||||
const con2 = await connectRemoteCouchDB(uri, auth);
|
const con2 = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
||||||
if (typeof con2 === "string") return;
|
if (typeof con2 === "string") return;
|
||||||
Logger("Remote Database Created or Connected", LOG_LEVEL.NOTICE);
|
Logger("Remote Database Created or Connected", LOG_LEVEL.NOTICE);
|
||||||
}
|
}
|
||||||
@@ -1109,7 +1109,7 @@ export class LocalPouchDB {
|
|||||||
username: setting.couchDB_USER,
|
username: setting.couchDB_USER,
|
||||||
password: setting.couchDB_PASSWORD,
|
password: setting.couchDB_PASSWORD,
|
||||||
};
|
};
|
||||||
const dbret = await connectRemoteCouchDB(uri, auth);
|
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
||||||
if (typeof dbret === "string") {
|
if (typeof dbret === "string") {
|
||||||
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
||||||
return;
|
return;
|
||||||
@@ -1143,7 +1143,7 @@ export class LocalPouchDB {
|
|||||||
username: setting.couchDB_USER,
|
username: setting.couchDB_USER,
|
||||||
password: setting.couchDB_PASSWORD,
|
password: setting.couchDB_PASSWORD,
|
||||||
};
|
};
|
||||||
const dbret = await connectRemoteCouchDB(uri, auth);
|
const dbret = await connectRemoteCouchDB(uri, auth, setting.disableRequestURI);
|
||||||
if (typeof dbret === "string") {
|
if (typeof dbret === "string") {
|
||||||
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
Logger(`could not connect to ${uri}:${dbret}`, LOG_LEVEL.NOTICE);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -14,10 +14,14 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
async testConnection(): Promise<void> {
|
async testConnection(): Promise<void> {
|
||||||
const db = await connectRemoteCouchDB(this.plugin.settings.couchDB_URI + (this.plugin.settings.couchDB_DBNAME == "" ? "" : "/" + this.plugin.settings.couchDB_DBNAME), {
|
const db = await connectRemoteCouchDB(
|
||||||
username: this.plugin.settings.couchDB_USER,
|
this.plugin.settings.couchDB_URI + (this.plugin.settings.couchDB_DBNAME == "" ? "" : "/" + this.plugin.settings.couchDB_DBNAME),
|
||||||
password: this.plugin.settings.couchDB_PASSWORD,
|
{
|
||||||
});
|
username: this.plugin.settings.couchDB_USER,
|
||||||
|
password: this.plugin.settings.couchDB_PASSWORD,
|
||||||
|
},
|
||||||
|
this.plugin.settings.disableRequestURI
|
||||||
|
);
|
||||||
if (typeof db === "string") {
|
if (typeof db === "string") {
|
||||||
this.plugin.addLog(`could not connect to ${this.plugin.settings.couchDB_URI} : ${this.plugin.settings.couchDB_DBNAME} \n(${db})`, LOG_LEVEL.NOTICE);
|
this.plugin.addLog(`could not connect to ${this.plugin.settings.couchDB_URI} : ${this.plugin.settings.couchDB_DBNAME} \n(${db})`, LOG_LEVEL.NOTICE);
|
||||||
return;
|
return;
|
||||||
@@ -165,6 +169,12 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
this.plugin.settings.couchDB_DBNAME = value;
|
this.plugin.settings.couchDB_DBNAME = value;
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
})
|
})
|
||||||
|
),
|
||||||
|
new Setting(containerRemoteDatabaseEl).setName("Use the old connecting method").addToggle((toggle) =>
|
||||||
|
toggle.setValue(this.plugin.settings.disableRequestURI).onChange(async (value) => {
|
||||||
|
this.plugin.settings.disableRequestURI = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -603,7 +613,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
);
|
);
|
||||||
|
|
||||||
new Setting(containerMiscellaneousEl)
|
new Setting(containerMiscellaneousEl)
|
||||||
.setName("Use history (beta)")
|
.setName("Use history")
|
||||||
.setDesc("Use history dialog (Restart required, auto compaction would be disabled, and more storage will be consumed)")
|
.setDesc("Use history dialog (Restart required, auto compaction would be disabled, and more storage will be consumed)")
|
||||||
.addToggle((toggle) =>
|
.addToggle((toggle) =>
|
||||||
toggle.setValue(this.plugin.settings.useHistory).onChange(async (value) => {
|
toggle.setValue(this.plugin.settings.useHistory).onChange(async (value) => {
|
||||||
@@ -832,12 +842,6 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
new Setting(containerPluginSettings).setName("Show own plugins and settings").addToggle((toggle) =>
|
|
||||||
toggle.setValue(this.plugin.settings.showOwnPlugins).onChange(async (value) => {
|
|
||||||
this.plugin.settings.showOwnPlugins = value;
|
|
||||||
await this.plugin.saveSettings();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
new Setting(containerPluginSettings)
|
new Setting(containerPluginSettings)
|
||||||
.setName("Sweep plugins automatically")
|
.setName("Sweep plugins automatically")
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ export interface ObsidianLiveSyncSettings {
|
|||||||
batch_size: number;
|
batch_size: number;
|
||||||
batches_limit: number;
|
batches_limit: number;
|
||||||
useHistory: boolean;
|
useHistory: boolean;
|
||||||
|
disableRequestURI: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = {
|
export const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = {
|
||||||
@@ -101,6 +102,7 @@ export const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = {
|
|||||||
batch_size: 250,
|
batch_size: 250,
|
||||||
batches_limit: 40,
|
batches_limit: 40,
|
||||||
useHistory: false,
|
useHistory: false,
|
||||||
|
disableRequestURI: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PERIODIC_PLUGIN_SWEEP = 60;
|
export const PERIODIC_PLUGIN_SWEEP = 60;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Logger } from "./logger";
|
|||||||
import { LOG_LEVEL, VER, VERSIONINFO_DOCID, EntryVersionInfo, EntryDoc } from "./types";
|
import { LOG_LEVEL, VER, VERSIONINFO_DOCID, EntryVersionInfo, EntryDoc } from "./types";
|
||||||
import { resolveWithIgnoreKnownError } from "./utils";
|
import { resolveWithIgnoreKnownError } from "./utils";
|
||||||
import { PouchDB } from "../pouchdb-browser-webpack/dist/pouchdb-browser.js";
|
import { PouchDB } from "../pouchdb-browser-webpack/dist/pouchdb-browser.js";
|
||||||
|
import { requestUrl, RequestUrlParam } from "obsidian";
|
||||||
|
|
||||||
export const isValidRemoteCouchDBURI = (uri: string): boolean => {
|
export const isValidRemoteCouchDBURI = (uri: string): boolean => {
|
||||||
if (uri.startsWith("https://")) return true;
|
if (uri.startsWith("https://")) return true;
|
||||||
@@ -12,8 +13,17 @@ let last_post_successed = false;
|
|||||||
export const getLastPostFailedBySize = () => {
|
export const getLastPostFailedBySize = () => {
|
||||||
return !last_post_successed;
|
return !last_post_successed;
|
||||||
};
|
};
|
||||||
export const connectRemoteCouchDB = async (uri: string, auth: { username: string; password: string }): Promise<string | { db: PouchDB.Database<EntryDoc>; info: PouchDB.Core.DatabaseInfo }> => {
|
|
||||||
|
export const connectRemoteCouchDB = async (uri: string, auth: { username: string; password: string }, disableRequestURI: boolean): Promise<string | { db: PouchDB.Database<EntryDoc>; info: PouchDB.Core.DatabaseInfo }> => {
|
||||||
if (!isValidRemoteCouchDBURI(uri)) return "Remote URI is not valid";
|
if (!isValidRemoteCouchDBURI(uri)) return "Remote URI is not valid";
|
||||||
|
let authHeader = "";
|
||||||
|
if (auth.username && auth.password) {
|
||||||
|
const utf8str = String.fromCharCode.apply(null, new TextEncoder().encode(`${auth.username}:${auth.password}`));
|
||||||
|
const encoded = window.btoa(utf8str);
|
||||||
|
authHeader = "Basic " + encoded;
|
||||||
|
} else {
|
||||||
|
authHeader = "";
|
||||||
|
}
|
||||||
const conf: PouchDB.HttpAdapter.HttpAdapterConfiguration = {
|
const conf: PouchDB.HttpAdapter.HttpAdapterConfiguration = {
|
||||||
adapter: "http",
|
adapter: "http",
|
||||||
auth,
|
auth,
|
||||||
@@ -35,6 +45,54 @@ export const connectRemoteCouchDB = async (uri: string, auth: { username: string
|
|||||||
}
|
}
|
||||||
size = ` (${opts_length})`;
|
size = ` (${opts_length})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!disableRequestURI && typeof url == "string" && typeof (opts.body ?? "") == "string") {
|
||||||
|
const body = opts.body as string;
|
||||||
|
|
||||||
|
const transformedHeaders = { ...(opts.headers as Record<string, string>) };
|
||||||
|
if (authHeader != "") transformedHeaders["authorization"] = authHeader;
|
||||||
|
delete transformedHeaders["host"];
|
||||||
|
delete transformedHeaders["Host"];
|
||||||
|
delete transformedHeaders["content-length"];
|
||||||
|
delete transformedHeaders["Content-Length"];
|
||||||
|
const requestParam: RequestUrlParam = {
|
||||||
|
url: url as string,
|
||||||
|
method: opts.method,
|
||||||
|
body: body,
|
||||||
|
headers: transformedHeaders,
|
||||||
|
contentType: "application/json",
|
||||||
|
// contentType: opts.headers,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const r = await requestUrl(requestParam);
|
||||||
|
if (method == "POST" || method == "PUT") {
|
||||||
|
last_post_successed = r.status - (r.status % 100) == 200;
|
||||||
|
} else {
|
||||||
|
last_post_successed = true;
|
||||||
|
}
|
||||||
|
if (r.status - (r.status % 100) !== 200) {
|
||||||
|
throw new Error(`Request Error:${r.status}`);
|
||||||
|
}
|
||||||
|
Logger(`HTTP:${method}${size} to:${localURL} -> ${r.status}`, LOG_LEVEL.VERBOSE);
|
||||||
|
|
||||||
|
return new Response(r.arrayBuffer, {
|
||||||
|
headers: r.headers,
|
||||||
|
status: r.status,
|
||||||
|
statusText: `${r.status}`,
|
||||||
|
});
|
||||||
|
} catch (ex) {
|
||||||
|
Logger(`HTTP:${method}${size} to:${localURL} -> failed`, LOG_LEVEL.VERBOSE);
|
||||||
|
if (!size_ok && (method == "POST" || method == "PUT")) {
|
||||||
|
last_post_successed = false;
|
||||||
|
}
|
||||||
|
Logger(ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -old implementation
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const responce: Response = await fetch(url, opts);
|
const responce: Response = await fetch(url, opts);
|
||||||
if (method == "POST" || method == "PUT") {
|
if (method == "POST" || method == "PUT") {
|
||||||
|
|||||||
Reference in New Issue
Block a user