[storage] #38: add Backblaze B2 as a first-class storage provider

B2 doesn't map onto the generic-S3 "paste an endpoint" model: its S3-compatible
endpoint is region-scoped (s3.<region>.backblazeb2.com) and a public bucket is
addressed virtual-hosted-style, so the public download URL is
https://<bucket>.s3.<region>.backblazeb2.com/<key> — not derivable from a pasted
generic endpoint. So B2 silently failed under "Custom S3".

- s3-url: deriveB2Endpoint(region) -> https://s3.<region>.backblazeb2.com (empty for
  auto/blank/pasted-host so callers can require a real region); re-exported from
  s3Service.
- storageService: PROVIDERS.B2 + resolveB2Endpoint (explicit endpoint wins, else
  derive) + PROVIDER_TESTS[B2] (derived endpoint, forcePathStyle false).
- Public URL = S3-style virtual-hosted, auto-derived; an explicit Public Access URL
  (custom domain/CDN) overrides it. The save path now forwards the user's public URL
  to prepareS3Connection (also fixes generic-S3 ignoring a custom CDN URL when blank
  -> still derives, so no regression).
- UI: "Backblaze B2" provider option + helper; raw Endpoint hidden for B2 (region
  drives it), region shows a us-west-004 example, force-path-style toggle hidden;
  save/test derive endpoint from region with a clear "enter your region" error.
  UploadModal shows B2-specific labels.
- Tests: tests/storage-b2-provider.test.mjs (8). All s3/storage suites green (50);
  build + lint clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-06-30 10:05:53 -04:00
1 parent 35bb1bc576
commit e79595b902
8 files changed
+259 -19

No files matched your search

+6
View File
@@ -898,6 +898,7 @@
<span class="mb-2 block font-medium">Provider</span>
<select id="storageProvider" class="input">
<option value="cloudflare_r2" selected>Cloudflare R2</option>
<option value="backblaze_b2">Backblaze B2</option>
<option value="generic_s3">Custom S3</option>
</select>
</label>
@@ -907,6 +908,11 @@
Enter your Cloudflare R2 credentials. Your Account ID (from dashboard) is used to connect. For Public Access URL, use your custom domain or R2.dev subdomain. Ensure the token has "Object Read & Write" permissions.
</div>
<!-- B2 Helper -->
<div id="storageB2Helper" class="card border border-info/30 bg-info/10 p-3 text-xs text-info hidden">
Enter your Backblaze B2 Application Key. Set Region to your bucket's region (e.g. us-west-004) — bitvid derives the endpoint and the public URL (https://&lt;bucket&gt;.s3.&lt;region&gt;.backblazeb2.com). Your bucket must be Public for playback; override the Public Access URL if you serve files from a custom domain/CDN.
</div>
<!-- S3 Helper -->
<div id="storageS3Helper" class="card border border-info/30 bg-info/10 p-3 text-xs text-info hidden">
Enter your S3-compatible storage details. The Endpoint URL is your provider's API address (e.g., https://s3.amazonaws.com or your MinIO URL).