Storage

View as Markdown

Storage gives workspaces a place to save and retrieve files — screenshots, downloads, CSV exports, PDFs. Each workspace can have its own storage namespace, and multiple workspaces can share one.

Access via bctrl.storage(workspaceName).

1const storage = bctrl.storage("my-workspace");

upload(filePath, data, filename?)

Upload a file to workspace storage.

1await storage.upload("exports/report.csv", csvBuffer);
2
3// With explicit filename
4await storage.upload("exports/report.csv", csvBuffer, "q1-report.csv");
ParameterTypeRequiredDescription
filePathstringYesLogical path in storage (e.g., exports/report.csv)
dataBuffer | Uint8Array | BlobYesFile content
filenamestringNoOverride the filename (defaults to last segment of filePath)

Returns UploadResult


uploadObject(data, options?)

Upload a file and register it in the object catalog. Use this when you want storage objects to be queryable by source, runtime, driver, etc.

1await storage.uploadObject(screenshotBuffer, {
2 source: "screenshot",
3 runtimeId: "browser-1",
4 filename: "homepage.png",
5});
ParameterTypeRequiredDescription
dataBuffer | Uint8Array | BlobYesFile content
options.sourcestringNoSource identifier (e.g., screenshot, download)
options.runtimeIdstringNoAssociated runtime ID
options.driverstringNoDriver that produced this object
options.filenamestringNoFilename

Returns UploadObjectResult


get(filePath)

Download a file as raw bytes.

1const data = await storage.get("exports/report.csv");
ParameterTypeRequiredDescription
filePathstringYesLogical path in storage

Returns Buffer


getDownloadUrl(filePath)

Get a presigned URL for direct download.

1const url = await storage.getDownloadUrl("exports/report.csv");
ParameterTypeRequiredDescription
filePathstringYesLogical path in storage

Returns string — presigned download URL.


browse(options?)

Browse files and folders with hierarchical listing.

1const result = await storage.browse({ prefix: "exports/", limit: 50 });
2for (const file of result.files) {
3 console.log(file.path, file.size);
4}
ParameterTypeRequiredDescription
prefixstringNoPath prefix to filter
cursorstringNoPagination cursor
limitnumberNoMax results

Returns StorageBrowseResult


read(filePath, maxBytes?)

Read a UTF-8 text preview of a file.

1const result = await storage.read("exports/report.csv", 1024);
2console.log(result.content);
ParameterTypeRequiredDescription
filePathstringYesLogical path
maxBytesnumberNoMax bytes to read

Returns StorageReadResult


listObjects(options?)

List objects from the storage catalog with metadata filters.

1const objects = await storage.listObjects({
2 source: "screenshot",
3 runtimeId: "browser-1",
4});
ParameterTypeRequiredDescription
sourcestringNoFilter by source
runtimeIdstringNoFilter by runtime
driverstringNoFilter by driver
pathPrefixstringNoFilter by path prefix
limitnumberNoMax results
offsetnumberNoSkip first N results

Returns StorageObject[]


downloadObject(id)

Download an object by its catalog ID.

1const data = await storage.downloadObject("obj_abc123");

Returns Buffer


getObjectDownloadUrl(id)

Get a presigned URL for an object by catalog ID.

1const url = await storage.getObjectDownloadUrl("obj_abc123");

Returns string


getDownloadsZip()

Download all files as a single ZIP archive.

1const zip = await storage.getDownloadsZip();

Returns Buffer — ZIP file content.


delete(filePath)

Delete a file by logical path.

1await storage.delete("exports/report.csv");

deleteObject(id)

Delete an object by catalog ID.

1await storage.deleteObject("obj_abc123");

deleteAll()

Delete all files in this workspace’s storage.

1const count = await storage.deleteAll();
2console.log(`Deleted ${count} files`);

Returns number — count of deleted files.


forWorkspace(workspace)

Create a client for a different workspace namespace, preserving the same auth.

1const otherStorage = storage.forWorkspace("other-workspace");

Returns StorageClient


Usage with workspaces

Storage is mounted to workspaces via the storage mount. See Scopes & Inheritance.

1const workspace = await bctrl.workspaces.create({
2 name: "data-pipeline",
3 mounts: {
4 storage: { workspace: "shared-exports" },
5 },
6});