mirror of
https://github.com/andrewkopylev/vaultbridge.git
synced 2026-07-22 06:50:15 +00:00
Release 0.9.10 — fix zero-byte download crash, simplify Password setDesc
This commit is contained in:
parent
bbe554fdaa
commit
e5c5d23dea
6 changed files with 19 additions and 9 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "vault-bridge-sftp",
|
||||
"name": "Vault Bridge SFTP",
|
||||
"version": "0.9.9",
|
||||
"version": "0.9.10",
|
||||
"minAppVersion": "1.5.0",
|
||||
"description": "Bridge your vault across devices through your own SSH/SFTP server. Bidirectional sync with conflict resolution, multi-device safety, and full self-hosting.",
|
||||
"author": "Andrew Kopylev",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "obsidian-vault-bridge-sftp",
|
||||
"version": "0.9.9",
|
||||
"version": "0.9.10",
|
||||
"description": "Vault Bridge SFTP — bidirectional Obsidian vault sync over SSH/SFTP",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ export class SftpSyncSettingTab extends PluginSettingTab {
|
|||
if (this.plugin.settings.authMethod === "password") {
|
||||
new Setting(containerEl)
|
||||
.setName("Password")
|
||||
.setDesc("Encrypted at rest using a per-device key. The key never syncs to the server, so password disclosure requires local filesystem access. SSH keys are still preferred on shared machines.")
|
||||
.setDesc("Encrypted on this device. Use SSH keys on shared machines.")
|
||||
.addText((t) => {
|
||||
t.inputEl.type = "password";
|
||||
t.setValue(this.plugin.settings.password).onChange((v) => {
|
||||
|
|
|
|||
|
|
@ -85,15 +85,22 @@ export async function readLocalAsBuffer(adapter: DataAdapter, vaultPath: string)
|
|||
return Buffer.from(ab);
|
||||
}
|
||||
|
||||
/** Read a remote file as a Buffer (full content in memory). */
|
||||
/** Read a remote file as a Buffer (full content in memory).
|
||||
* Note: ssh2-sftp-client's `get()` (via the underlying concat-stream) returns an empty
|
||||
* array `[]` instead of an empty Buffer when the remote file is zero bytes, so we
|
||||
* defensively coerce to a real Buffer here. Callers downstream rely on `.buffer`,
|
||||
* `.byteOffset`, and `Buffer.isBuffer` semantics that the empty-array sentinel
|
||||
* doesn't satisfy. */
|
||||
export async function downloadToBuffer(
|
||||
client: SftpClient,
|
||||
remoteRoot: string,
|
||||
vaultPath: string,
|
||||
): Promise<Buffer> {
|
||||
const remotePath = remotePathOf(remoteRoot, vaultPath);
|
||||
const buf = (await client.raw.get(remotePath)) as Buffer;
|
||||
return buf;
|
||||
const result = await client.raw.get(remotePath);
|
||||
if (Buffer.isBuffer(result)) return result;
|
||||
// 0-byte file → concat-stream gave us [] — return a real empty Buffer instead.
|
||||
return Buffer.alloc(0);
|
||||
}
|
||||
|
||||
/** Write a Buffer into the vault at `vaultPath`, atomically via the given tmp directory.
|
||||
|
|
|
|||
|
|
@ -174,10 +174,12 @@ export class PullEngine {
|
|||
): Promise<void> {
|
||||
const remotePath = remotePathOf(this.settings.remoteRoot, vaultPath);
|
||||
|
||||
// Get full file content. ssh2-sftp-client.get returns a Buffer when no stream destination is given.
|
||||
// Get full file content. ssh2-sftp-client.get returns a Buffer for non-empty files,
|
||||
// but an empty array `[]` (via concat-stream) for zero-byte files. Coerce to Buffer.
|
||||
let buf: Buffer;
|
||||
try {
|
||||
buf = (await client.raw.get(remotePath)) as Buffer;
|
||||
const result = await client.raw.get(remotePath);
|
||||
buf = Buffer.isBuffer(result) ? result : Buffer.alloc(0);
|
||||
} catch (err) {
|
||||
throw new Error(`Cannot fetch remote ${remotePath}: ${(err as Error).message}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,5 +2,6 @@
|
|||
"0.9.6": "1.5.0",
|
||||
"0.9.7": "1.5.0",
|
||||
"0.9.8": "1.5.0",
|
||||
"0.9.9": "1.5.0"
|
||||
"0.9.9": "1.5.0",
|
||||
"0.9.10": "1.5.0"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue