mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-02 19:02:28 +00:00
feat(my-videos): bucket object listing for reconciliation (Phase 2, step 2)
Adds the bucket-enumeration primitive the My Videos tab needs to find orphan and
missing files:
- s3 layer: ListObjectsV2Command wired into the SDK wrapper + a paginated
listObjects({ s3, bucket, prefix, maxKeys }) helper (follows continuation
tokens, bounded by maxKeys).
- r2Service.listVideoStorageObjects({ npub|pubkey }) — unlock-gated, lists under
the user's own u/<npub>/ prefix; returns { ok, reason, keys }. Body lives in
r2ServiceHelpers (with a shared buildProviderClient) so r2Service stays under
its file-size budget; ensureS3SdkLoaded is injectable via ctx for testing.
Tests + mutation-verified: never lists while locked (storage-locked, no call),
no-connection / missing-bucket gating, and unlocked listing is scoped to the
user's own u/<npub>/ prefix (empty-prefix mutation fails). Removing the lock gate
or widening the prefix each fail a scenario.
Build + full lint green (r2Service back under limit).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
bbb8dd0fd8
commit
513f75e4da
6 files changed
+233
-2
No files matched your search
@@ -35,6 +35,7 @@ import {
|
||||
ensureBucketCors,
|
||||
ensureBucketExists,
|
||||
deleteObject,
|
||||
listObjects,
|
||||
} from "../storage/s3-multipart.js";
|
||||
import { ensureS3SdkLoaded, makeS3Client } from "../storage/s3-client.js";
|
||||
import { truncateMiddle } from "../utils/formatters.js";
|
||||
@@ -60,6 +61,7 @@ import {
|
||||
createDefaultSettings,
|
||||
safeDecodeNpub,
|
||||
verifyPublicAccess as verifyPublicAccessHelper,
|
||||
listVideoStorageObjects as listVideoStorageObjectsHelper,
|
||||
} from "./r2ServiceHelpers.js";
|
||||
|
||||
const STATUS_VARIANTS = new Set(["info", "success", "error", "warning"]);
|
||||
@@ -76,6 +78,7 @@ export class R2Service {
|
||||
ensureBucketExists: ensureBucketExistsOverride,
|
||||
ensureBucketCors: ensureBucketCorsOverride,
|
||||
deleteObject: deleteObjectOverride,
|
||||
listObjects: listObjectsOverride,
|
||||
} = {}) {
|
||||
this.listeners = new Map();
|
||||
this.cloudflareSettings = null;
|
||||
@@ -85,6 +88,7 @@ export class R2Service {
|
||||
this.ensureBucketExists = ensureBucketExistsOverride || ensureBucketExists;
|
||||
this.ensureBucketCors = ensureBucketCorsOverride || ensureBucketCors;
|
||||
this.deleteObject = deleteObjectOverride || deleteObject;
|
||||
this.listObjects = listObjectsOverride || listObjects;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,6 +230,15 @@ export class R2Service {
|
||||
return summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the object keys under the user's storage prefix (u/<npub>/) so the
|
||||
* "My Videos" tab can reconcile notes against actual bucket contents. Unlock-
|
||||
* gated (needs credentials); returns { ok, reason, keys }.
|
||||
*/
|
||||
async listVideoStorageObjects(args = {}) {
|
||||
return listVideoStorageObjectsHelper(this, args);
|
||||
}
|
||||
|
||||
on(event, handler) {
|
||||
if (typeof handler !== "function") {
|
||||
return () => {};
|
||||
|
||||
Reference in new issue
Block a user