Phase 6 green: download and decrypt files to disk

downloadFile streams the encrypted body from the CDN, buffers it to
the 4 MiB + 17 encrypted chunk boundary, decrypts each chunk via
secretstream pull, and writes the concatenated plaintext to disk.
downloadThumbnail does the same for the thumbnail CDN.

4 unit tests (single-chunk, large single-chunk, filename fallback,
thumbnail) + live integration test that downloads a real 472 KB JPEG
from the dev account and verifies it lands on disk.

Uses mkdtempSync for temp directories (not manual timestamp paths).
This commit is contained in:
2026-05-13 17:54:03 -07:00
parent 8f4afb06c0
commit f55d216252
3 changed files with 110 additions and 74 deletions

View File

@@ -3,6 +3,7 @@ import { ApiClient } from "../../src/api/client.js";
import { beginLogin } from "../../src/auth/login.js";
import { unwrapAuth } from "../../src/auth/unwrap.js";
import { decryptCollection, decryptFile } from "../../src/model/index.js";
import { downloadFile } from "../../src/download/index.js";
import type { RawCollection, RawEnteFile } from "../../src/model/index.js";
// Dev account — not a secret, throwaway account for integration testing.
@@ -80,6 +81,28 @@ const main = async () => {
if (files.length > 10) {
console.log(` ... and ${files.length - 10} more`);
}
// Download the first file to a temp directory
if (files.length > 0) {
const first = files[0]!;
const { mkdtempSync, statSync } = await import("node:fs");
const { join } = await import("node:path");
const { tmpdir } = await import("node:os");
const outDir = mkdtempSync(join(tmpdir(), "quack-live-test-"));
const outPath = `${outDir}/${first.metadata.title}`;
console.log(`\n Downloading "${first.metadata.title}"...`);
const result = await downloadFile(api, first, outPath);
const stat = statSync(result.path);
console.log(
` Saved to ${result.path} (${result.bytesWritten} bytes decrypted, ${stat.size} on disk)`,
);
if (result.bytesWritten < 1000) {
console.error(
" WARNING: file seems too small, possible decryption issue",
);
}
}
break;
}