useMongocampBucket
Detection and file operations for GridFS bucket collections. Powers the upload/download support in MongocampCollectionData, the bucket-level actions in MongocampCollections, and the file-level browsing/management in MongocampBucketFiles.
const {
isBucketCollection, // (collectionName: string) => boolean
bucketNameFor, // (collectionName: string) => string
fileIdForRow, // (collectionName: string, row: Record<string, unknown>) => string | undefined
downloadingFileIds, // Ref<Set<string>>
uploading, // Ref<boolean>
downloadFile, // (collectionName: string, fileId: string) => Promise<void>
uploadFile, // (collectionName: string, file: File) => Promise<boolean>
bucketActionInFlight, // Ref<Set<string>> — bucket names with a clear/delete in progress
fileActionInFlight, // Ref<Set<string>> — file ids with a delete/rename in progress
listFiles, // (bucketName: string, options?: ListFilesOptions) => Promise<ListFilesResult>
deleteFile, // (bucketName: string, fileId: string) => Promise<boolean>
updateFileInformation, // (bucketName: string, fileId: string, options: UpdateFileInformationOptions) => Promise<boolean>
listBuckets, // () => Promise<string[]>
getBucketInfo, // (bucketName: string) => Promise<BucketInformation>
clearBucket, // (bucketName: string) => Promise<boolean>
deleteBucket, // (bucketName: string) => Promise<boolean>
} = useMongocampBucket()Background: a bucket is two collections
Uploading a file through a GridFS bucket (fileApi.insertFile) creates/uses two real Mongo collections: <bucketName>.files (one document per file, with filename/length/metadata) and <bucketName>.chunks (the binary chunks). Both appear in collectionApi.listCollections() like any other collection.
Detecting and naming buckets
isBucketCollection('images.files') // true
isBucketCollection('images.chunks') // true
isBucketCollection('customers') // false
bucketNameFor('images.files') // 'images'
bucketNameFor('images.chunks') // 'images'Resolving a file id from a row
Which field holds the file id depends on which half of the bucket you're looking at:
- On a
.filesrow, the file id is the row's_id. - On a
.chunksrow, the file id is the row'sfiles_id(its own_idis the chunk id).
fileIdForRow('images.files', { _id: { $oid: 'abc123' } }) // 'abc123'
fileIdForRow('images.chunks', { files_id: 'abc123', _id: 'c1' }) // 'abc123'Both _id and files_id may arrive as a plain string or as extended-JSON { $oid: '...' } — fileIdForRow unwraps either shape.
Downloading a file
await downloadFile('images.files', fileId)Fetches fileApi.getFileInformation (for the real filename) and fileApi.getFile (the blob), then triggers a browser download. Falls back to the raw file id as the download name if no filename is known. Tracks in-flight downloads in downloadingFileIds (add a :loading="downloadingFileIds.has(fileId)" binding on your button) and shows an error toast on failure.
Uploading a file
const success = await uploadFile('images.files', file) // file: File
if (success) await fetchDocuments() // refresh the tableUploads via fileApi.insertFile, targeting the bucket regardless of whether collectionName was the .files or .chunks half. Tracks the in-flight upload in uploading and shows a success/error toast; returns true/false so the caller knows whether to refresh.
Listing, deleting, and renaming individual files
Unlike downloadFile/uploadFile (which work per-file but need a resolved id from a raw document row), these operate directly against a bucket name and return/accept the clean, typed FileInformation shape (id, filename, length, chunkSize, uploadDate, metadata) — no extended-JSON unwrapping needed:
const { files, total } = await listFiles('images', {
filter: 'filename:*.png', // Lucene filter string, same convention as useMongocampQuery
sort: '-uploadDate',
page: 1,
rowsPerPage: 20,
})
const deleted = await deleteFile('images', fileId)
const renamed = await updateFileInformation('images', fileId, { filename: 'new-name.png', metadata: { owner: 'alice' } })listFiles reads the total row count from the x-pagination-count-rows response header (same convention MongocampCollectionData uses for documents), returning 0 if the header is absent. deleteFile/updateFileInformation follow the same loading-state/toast/boolean-return convention as every other mutation here — both track in-flight file ids via fileActionInFlight (bind :loading="fileActionInFlight.has(fileId)"), show a success/error toast, and return a boolean so the caller knows whether to refresh.
Bucket-level operations
Unlike the per-file methods above, these operate on the whole bucket (both its .files and .chunks collections at once) via the raw bucketApi, not fileApi:
const buckets = await listBuckets() // ['images', 'avatars', ...]
const info = await getBucketInfo('images') // { name, files, size, avgObjectSize }
const cleared = await clearBucket('images') // deletes every file in the bucket, keeps the bucket
const deleted = await deleteBucket('images') // drops both images.files and images.chunks entirelyclearBucket/deleteBucket follow the same convention as uploadFile: they track their own loading state (bucketActionInFlight, keyed by bucket name — bind :loading="bucketActionInFlight.has(bucketName)"), show a success/error toast, and return a boolean so the caller knows whether to refresh.