The Bucket class represents a Cloud Storage bucket and provides comprehensive methods for file management, metadata operations, lifecycle rules, and access control.
class Bucket extends ServiceObject {
constructor(storage: Storage, name: string, options?: BucketOptions);
// Properties
name: string;
storage: Storage;
acl: Acl;
iam: Iam;
userProject?: string;
metadata: BucketMetadata;
cloudStorageURI: URL;
// File management methods
file(name: string, options?: FileOptions): File;
getFiles(options?: GetFilesOptions): Promise<GetFilesResponse>;
getFilesStream(query?: GetFilesOptions): Readable;
upload(pathString: string, options?: UploadOptions): Promise<UploadResponse>;
deleteFiles(query?: DeleteFilesOptions): Promise<void>;
combine(sources: (File | string)[], destination: File | string, options?: CombineOptions): Promise<CombineResponse>;
// Bucket metadata and management
exists(options?: BucketExistsOptions): Promise<BucketExistsResponse>;
get(options?: GetBucketOptions): Promise<GetBucketResponse>;
getMetadata(options?: GetBucketMetadataOptions): Promise<GetBucketMetadataResponse>;
setMetadata(metadata: BucketMetadata, options?: SetBucketMetadataOptions): Promise<SetBucketMetadataResponse>;
delete(options?: DeleteBucketOptions): Promise<DeleteBucketResponse>;
restore(options?: RestoreBucketOptions): Promise<RestoreBucketResponse>;
// Retention policy management
setRetentionPeriod(period: number, options?: SetRetentionPeriodOptions): Promise<SetBucketMetadataResponse>;
removeRetentionPeriod(options?: RemoveRetentionPeriodOptions): Promise<SetBucketMetadataResponse>;
// Configuration helpers
setCorsConfiguration(cors: Cors[], options?: SetCorsOptions): Promise<SetBucketMetadataResponse>;
setUserProject(projectId: string): void;
enableLogging(config: LoggingConfig, options?: EnableLoggingOptions): Promise<SetBucketMetadataResponse>;
// Notifications
notification(id: string): Notification;
// Low-level access
request(options: RequestOptions): Promise<RequestResponse>;
}
interface BucketOptions {
crc32cGenerator?: CRC32CValidatorGenerator;
kmsKeyName?: string;
preconditionOpts?: PreconditionOptions;
userProject?: string;
generation?: number;
softDeleted?: boolean;
}file(name: string, options?: FileOptions): File
// Get file reference
const file = bucket.file('path/to/file.txt');
// With options
const file = bucket.file('path/to/file.txt', {
generation: 1234567890,
encryptionKey: 'base64-encoded-key'
});
// With KMS encryption
const file = bucket.file('encrypted-file.txt', {
kmsKeyName: 'projects/PROJECT_ID/locations/LOCATION/keyRings/RING_ID/cryptoKeys/KEY_ID'
});upload(pathString: string, options?: UploadOptions): Promise<UploadResponse>
interface UploadOptions {
destination?: string;
encryptionKey?: string | Buffer;
gzip?: boolean;
metadata?: FileMetadata;
offset?: number;
predefinedAcl?: PredefinedAcl;
private?: boolean;
public?: boolean;
resumable?: boolean;
timeout?: number;
uri?: string;
userProject?: string;
validation?: string | boolean;
preconditionOpts?: PreconditionOptions;
chunkSize?: number;
}
type UploadResponse = [File, unknown]; // [file, apiResponse]
// Simple upload
const [file] = await bucket.upload('/local/path/file.txt');
// Upload with custom destination
const [file] = await bucket.upload('/local/path/file.txt', {
destination: 'remote/path/renamed-file.txt'
});
// Upload with metadata
const [file] = await bucket.upload('/local/path/image.jpg', {
metadata: {
contentType: 'image/jpeg',
cacheControl: 'public, max-age=86400',
metadata: {
originalName: 'vacation-photo.jpg',
uploadedBy: 'user-123'
}
}
});
// Upload with compression
const [file] = await bucket.upload('/local/path/large-file.txt', {
gzip: true,
metadata: {
contentEncoding: 'gzip'
}
});
// Upload with encryption
const [file] = await bucket.upload('/local/path/secret.txt', {
encryptionKey: crypto.randomBytes(32).toString('base64')
});
// Upload with access control
const [file] = await bucket.upload('/local/path/public-file.txt', {
public: true
});
// Resumable upload for large files
const [file] = await bucket.upload('/local/path/large-video.mp4', {
resumable: true,
chunkSize: 256 * 1024, // 256KB chunks
metadata: {
contentType: 'video/mp4'
}
});getFiles(options?: GetFilesOptions): Promise<GetFilesResponse>
getFilesStream(query?: GetFilesOptions): Readable
interface GetFilesOptions {
delimiter?: string;
directory?: string;
endOffset?: string;
includeFoldersAsPrefixes?: boolean;
includeTrailingDelimiter?: boolean;
maxResults?: number;
pageToken?: string;
prefix?: string;
startOffset?: string;
userProject?: string;
versions?: boolean;
autoPaginate?: boolean;
softDeleted?: boolean;
}
type GetFilesResponse = [File[], {}, unknown]; // [files, nextQuery, apiResponse]
// List all files
const [files] = await bucket.getFiles();
files.forEach(file => {
console.log(`File: ${file.name}`);
});
// List with prefix filter
const [files] = await bucket.getFiles({
prefix: 'uploads/'
});
// List files in a "directory"
const [files] = await bucket.getFiles({
prefix: 'images/',
delimiter: '/'
});
// List with pagination
const [files, nextQuery] = await bucket.getFiles({
maxResults: 100
});
if (nextQuery) {
const [moreFiles] = await bucket.getFiles(nextQuery);
}
// List all versions
const [files] = await bucket.getFiles({
versions: true
});
// Stream files for large lists
bucket.getFilesStream({ prefix: 'logs/' })
.on('data', file => {
console.log(`File: ${file.name}, Size: ${file.metadata.size}`);
})
.on('end', () => {
console.log('Finished listing files');
});
// List with date range
const [files] = await bucket.getFiles({
startOffset: '2023-01-01',
endOffset: '2023-12-31'
});deleteFiles(query?: DeleteFilesOptions): Promise<void>
interface DeleteFilesOptions {
prefix?: string;
delimiter?: string;
directory?: string;
versions?: boolean;
force?: boolean;
userProject?: string;
}
// Delete all files with prefix
await bucket.deleteFiles({
prefix: 'temp/'
});
// Delete all files in "directory"
await bucket.deleteFiles({
prefix: 'old-data/',
delimiter: '/'
});
// Delete all versions
await bucket.deleteFiles({
prefix: 'archived/',
versions: true
});
// Force delete (ignore errors)
await bucket.deleteFiles({
prefix: 'cleanup/',
force: true
});combine(sources: (File | string)[], destination: File | string, options?: CombineOptions): Promise<CombineResponse>
interface CombineOptions {
kmsKeyName?: string;
userProject?: string;
}
type CombineResponse = [File, unknown]; // [combinedFile, apiResponse]
// Combine files by name
const [combinedFile] = await bucket.combine([
'part1.txt',
'part2.txt',
'part3.txt'
], 'combined.txt');
// Combine File objects
const part1 = bucket.file('logs/part1.log');
const part2 = bucket.file('logs/part2.log');
const destination = bucket.file('logs/combined.log');
const [combinedFile] = await bucket.combine([part1, part2], destination);
// Combine with encryption
const [combinedFile] = await bucket.combine(
['encrypted-part1.txt', 'encrypted-part2.txt'],
'encrypted-combined.txt',
{
kmsKeyName: 'projects/PROJECT_ID/locations/us/keyRings/my-ring/cryptoKeys/my-key'
}
);exists(options?: BucketExistsOptions): Promise<BucketExistsResponse>
interface BucketExistsOptions {
userProject?: string;
}
type BucketExistsResponse = [boolean]; // [exists]
// Check if bucket exists
const [exists] = await bucket.exists();
if (exists) {
console.log('Bucket exists');
} else {
console.log('Bucket does not exist');
}get(options?: GetBucketOptions): Promise<GetBucketResponse>
interface GetBucketOptions extends GetBucketMetadataOptions {
autoCreate?: boolean;
location?: string;
storageClass?: string;
}
type GetBucketResponse = [Bucket, unknown]; // [bucket, apiResponse]
// Get bucket (create if doesn't exist)
const [bucket] = await bucket.get({
autoCreate: true,
location: 'us-central1'
});getMetadata(options?: GetBucketMetadataOptions): Promise<GetBucketMetadataResponse>
setMetadata(metadata: BucketMetadata, options?: SetBucketMetadataOptions): Promise<SetBucketMetadataResponse>
interface GetBucketMetadataOptions {
userProject?: string;
ifMetagenerationMatch?: number;
ifMetagenerationNotMatch?: number;
}
interface BucketMetadata {
acl?: AclMetadata[];
cors?: Cors[];
defaultEventBasedHold?: boolean;
defaultObjectAcl?: AclMetadata[];
encryption?: {
defaultKmsKeyName?: string;
};
iamConfiguration?: {
bucketPolicyOnly?: {
enabled?: boolean;
};
publicAccessPrevention?: 'inherited' | 'enforced';
uniformBucketLevelAccess?: {
enabled?: boolean;
};
};
labels?: { [key: string]: string };
lifecycle?: {
rule?: LifecycleRule[];
};
location?: string;
locationType?: string;
logging?: {
logBucket?: string;
logObjectPrefix?: string;
};
name?: string;
owner?: {
entity?: string;
entityId?: string;
};
projectNumber?: string;
retentionPolicy?: {
effectiveTime?: string;
isLocked?: boolean;
retentionPeriod?: number;
};
storageClass?: string;
timeCreated?: string;
updated?: string;
versioning?: {
enabled?: boolean;
};
website?: {
mainPageSuffix?: string;
notFoundPage?: string;
};
requesterPays?: boolean;
}
type GetBucketMetadataResponse = [BucketMetadata, unknown]; // [metadata, apiResponse]
type SetBucketMetadataResponse = [BucketMetadata, unknown]; // [metadata, apiResponse]
// Get bucket metadata
const [metadata] = await bucket.getMetadata();
console.log('Location:', metadata.location);
console.log('Storage Class:', metadata.storageClass);
console.log('Created:', metadata.timeCreated);
// Update bucket metadata
const [metadata] = await bucket.setMetadata({
website: {
mainPageSuffix: 'index.html',
notFoundPage: '404.html'
},
labels: {
environment: 'production',
team: 'frontend'
}
});
// Enable versioning
await bucket.setMetadata({
versioning: {
enabled: true
}
});
// Set CORS configuration
await bucket.setMetadata({
cors: [
{
origin: ['https://example.com', 'https://app.example.com'],
method: ['GET', 'POST', 'PUT', 'DELETE'],
responseHeader: ['Content-Type', 'x-custom-header'],
maxAgeSeconds: 3600
}
]
});addLifecycleRule(rule: LifecycleRule | LifecycleRule[], options?: AddLifecycleRuleOptions): Promise<SetBucketMetadataResponse>
interface LifecycleRule {
action: LifecycleAction;
condition: LifecycleCondition;
}
interface LifecycleAction {
type: 'Delete' | 'SetStorageClass' | 'AbortIncompleteMultipartUpload';
storageClass?: string;
}
interface LifecycleCondition {
age?: number;
createdBefore?: Date | string;
customTimeBefore?: Date | string;
daysSinceCustomTime?: number;
daysSinceNoncurrentTime?: number;
isLive?: boolean;
matchesStorageClass?: string[];
noncurrentTimeBefore?: Date | string;
numNewerVersions?: number;
}
interface AddLifecycleRuleOptions {
append?: boolean;
userProject?: string;
}
// Delete files older than 365 days
await bucket.addLifecycleRule({
action: { type: 'Delete' },
condition: { age: 365 }
});
// Move to Coldline after 30 days
await bucket.addLifecycleRule({
action: {
type: 'SetStorageClass',
storageClass: 'COLDLINE'
},
condition: { age: 30 }
});
// Delete old versions (keep only 5 newest)
await bucket.addLifecycleRule({
action: { type: 'Delete' },
condition: {
numNewerVersions: 5,
isLive: false
}
});
// Multiple rules at once
await bucket.addLifecycleRule([
{
action: { type: 'SetStorageClass', storageClass: 'NEARLINE' },
condition: { age: 7, matchesStorageClass: ['STANDARD'] }
},
{
action: { type: 'SetStorageClass', storageClass: 'ARCHIVE' },
condition: { age: 90, matchesStorageClass: ['NEARLINE'] }
},
{
action: { type: 'Delete' },
condition: { age: 2555 } // ~7 years
}
]);
// Abort incomplete multipart uploads
await bucket.addLifecycleRule({
action: { type: 'AbortIncompleteMultipartUpload' },
condition: { age: 7 }
});setStorageClass(storageClass: string, options?: SetBucketStorageClassOptions): Promise<SetBucketMetadataResponse>
interface SetBucketStorageClassOptions {
userProject?: string;
}
// Available storage classes
const storageClasses = [
'STANDARD',
'NEARLINE',
'COLDLINE',
'ARCHIVE',
'DURABLE_REDUCED_AVAILABILITY'
];
// Set bucket storage class
await bucket.setStorageClass('COLDLINE');
// Regional storage
await bucket.setStorageClass('REGIONAL');setRetentionPeriod(period: number, options?: SetRetentionPeriodOptions): Promise<SetBucketMetadataResponse>
interface SetRetentionPeriodOptions {
userProject?: string;
}
// Set retention period (in seconds)
await bucket.setRetentionPeriod(86400 * 30); // 30 days
// Set retention period with user project
await bucket.setRetentionPeriod(86400 * 365, {
userProject: 'billing-project-id'
});
// Equivalent using setMetadata
await bucket.setMetadata({
retentionPolicy: {
retentionPeriod: 86400 * 30
}
});removeRetentionPeriod(options?: RemoveRetentionPeriodOptions): Promise<SetBucketMetadataResponse>
interface RemoveRetentionPeriodOptions {
userProject?: string;
}
// Remove retention period (only possible if policy is not locked)
await bucket.removeRetentionPeriod();
// With user project
await bucket.removeRetentionPeriod({
userProject: 'billing-project-id'
});lock(metageneration: number | string): Promise<BucketLockResponse>
type BucketLockResponse = [BucketMetadata, unknown]; // [metadata, apiResponse]
// Lock retention policy (irreversible!)
const [metadata] = await bucket.lock(bucket.metadata.metageneration);
console.log('Retention policy locked until:', metadata.retentionPolicy.effectiveTime);makePublic(options?: MakeBucketPublicOptions): Promise<MakeBucketPublicResponse>
makePrivate(options?: MakeBucketPrivateOptions): Promise<MakeBucketPrivateResponse>
interface MakeBucketPublicOptions {
includeFiles?: boolean;
force?: boolean;
userProject?: string;
}
interface MakeBucketPrivateOptions {
includeFiles?: boolean;
force?: boolean;
userProject?: string;
}
type MakeBucketPublicResponse = [File[], unknown]; // [files, apiResponse]
type MakeBucketPrivateResponse = [File[], unknown]; // [files, apiResponse]
// Make bucket public (bucket and all files)
const [files] = await bucket.makePublic({
includeFiles: true
});
// Make bucket private
await bucket.makePrivate({
includeFiles: true
});
// Force operation (ignore errors)
await bucket.makePublic({
includeFiles: true,
force: true
});enableRequesterPays(options?: EnableRequesterPaysOptions): Promise<EnableRequesterPaysResponse>
disableRequesterPays(options?: DisableRequesterPaysOptions): Promise<DisableRequesterPaysResponse>
interface EnableRequesterPaysOptions {
userProject?: string;
}
interface DisableRequesterPaysOptions {
userProject?: string;
}
type EnableRequesterPaysResponse = [unknown]; // [apiResponse]
type DisableRequesterPaysResponse = [unknown]; // [apiResponse]
// Enable requester pays
await bucket.enableRequesterPays();
// Disable requester pays
await bucket.disableRequesterPays();setCorsConfiguration(cors: Cors[], options?: SetCorsOptions): Promise<SetBucketMetadataResponse>
interface SetCorsOptions {
userProject?: string;
}
interface Cors {
origin?: string[];
method?: string[];
responseHeader?: string[];
maxAgeSeconds?: number;
}
// Set CORS configuration
await bucket.setCorsConfiguration([
{
origin: ['https://example.com', 'https://app.example.com'],
method: ['GET', 'POST', 'PUT', 'DELETE'],
responseHeader: ['Content-Type', 'x-custom-header'],
maxAgeSeconds: 3600
}
]);
// Allow all origins (use carefully)
await bucket.setCorsConfiguration([
{
origin: ['*'],
method: ['GET', 'HEAD'],
responseHeader: ['*'],
maxAgeSeconds: 86400
}
]);setUserProject(projectId: string): void
// Set user project for billing
bucket.setUserProject('billing-project-id');
// All subsequent operations will use this project for billing
const [files] = await bucket.getFiles(); // Uses billing-project-id for billingenableLogging(config: LoggingConfig, options?: EnableLoggingOptions): Promise<SetBucketMetadataResponse>
interface LoggingConfig {
logBucket: string;
logObjectPrefix?: string;
}
interface EnableLoggingOptions {
userProject?: string;
}
// Enable access logging
await bucket.enableLogging({
logBucket: 'access-logs-bucket',
logObjectPrefix: 'my-bucket-logs/'
});
// Basic logging (no prefix)
await bucket.enableLogging({
logBucket: 'access-logs-bucket'
});getLabels(options?: GetLabelsOptions): Promise<GetLabelsResponse>
setLabels(labels: Labels, options?: SetLabelsOptions): Promise<SetLabelsResponse>
deleteLabels(labels?: string[], options?: DeleteLabelsOptions): Promise<DeleteLabelsResponse>
interface Labels {
[key: string]: string;
}
interface GetLabelsOptions {
userProject?: string;
}
interface SetLabelsOptions {
userProject?: string;
}
interface DeleteLabelsOptions {
userProject?: string;
}
type GetLabelsResponse = [Labels, unknown]; // [labels, apiResponse]
type SetLabelsResponse = [Labels, unknown]; // [labels, apiResponse]
type DeleteLabelsResponse = [Labels, unknown]; // [labels, apiResponse]
// Get current labels
const [labels] = await bucket.getLabels();
console.log('Current labels:', labels);
// Set labels
await bucket.setLabels({
environment: 'production',
team: 'backend',
cost_center: '12345'
});
// Delete specific labels
await bucket.deleteLabels(['cost_center']);
// Delete all labels
await bucket.deleteLabels();createNotification(topic: string, options?: CreateNotificationOptions): Promise<CreateNotificationResponse>
getNotifications(options?: GetNotificationsOptions): Promise<GetNotificationsResponse>
interface CreateNotificationOptions {
eventTypes?: string[];
objectNamePrefix?: string;
payloadFormat?: string;
userProject?: string;
}
interface GetNotificationsOptions {
userProject?: string;
}
type CreateNotificationResponse = [Notification, unknown]; // [notification, apiResponse]
type GetNotificationsResponse = [Notification[], unknown]; // [notifications, apiResponse]
// Create notification for all events
const [notification] = await bucket.createNotification('projects/my-project/topics/bucket-notifications');
// Create notification for specific events
const [notification] = await bucket.createNotification('projects/my-project/topics/bucket-uploads', {
eventTypes: ['OBJECT_FINALIZE'],
objectNamePrefix: 'uploads/',
payloadFormat: 'JSON_API_V1'
});
// List notifications
const [notifications] = await bucket.getNotifications();
notifications.forEach(notification => {
console.log(`Notification: ${notification.id}`);
});notification(id: string): Notification
// Get notification reference by ID
const notification = bucket.notification('notification-id-123');
// Use the reference to get metadata or delete
const [metadata] = await notification.getMetadata();
console.log('Topic:', metadata.topic);
// Delete the notification
await notification.delete();createChannel(id: string, config: CreateChannelConfig, options?: CreateChannelOptions): Promise<CreateChannelResponse>
interface CreateChannelConfig {
address: string;
type?: string;
token?: string;
params?: { [key: string]: string };
}
interface CreateChannelOptions {
userProject?: string;
}
type CreateChannelResponse = [Channel, unknown]; // [channel, apiResponse]
// Create watch channel
const [channel] = await bucket.createChannel('my-channel-id', {
address: 'https://example.com/webhook',
type: 'web_hook'
});
// With authentication token
const [channel] = await bucket.createChannel('secure-channel', {
address: 'https://api.example.com/storage-webhook',
token: 'secret-token-123'
});getSignedUrl(config: GetBucketSignedUrlConfig): Promise<GetSignedUrlResponse>
interface GetBucketSignedUrlConfig {
version: 'v2' | 'v4';
action: 'list';
expires: string | number | Date;
extensionHeaders?: { [key: string]: string };
queryParams?: { [key: string]: string };
cname?: string;
contentMd5?: string;
contentType?: string;
virtualHostedStyle?: boolean;
}
type GetSignedUrlResponse = [string]; // [signedUrl]
// Generate signed URL for listing bucket contents
const [url] = await bucket.getSignedUrl({
version: 'v4',
action: 'list',
expires: Date.now() + 15 * 60 * 1000 // 15 minutes
});
console.log('Signed URL:', url);
// With query parameters
const [url] = await bucket.getSignedUrl({
version: 'v4',
action: 'list',
expires: Date.now() + 3600000, // 1 hour
queryParams: {
prefix: 'uploads/',
delimiter: '/'
}
});delete(options?: DeleteBucketOptions): Promise<DeleteBucketResponse>
interface DeleteBucketOptions {
ignoreNotFound?: boolean;
userProject?: string;
ifMetagenerationMatch?: number;
ifMetagenerationNotMatch?: number;
}
type DeleteBucketResponse = [unknown]; // [apiResponse]
// Delete empty bucket
await bucket.delete();
// Delete bucket ignoring not found errors
await bucket.delete({
ignoreNotFound: true
});restore(options?: RestoreBucketOptions): Promise<RestoreBucketResponse>
interface RestoreBucketOptions {
userProject?: string;
ifMetagenerationMatch?: number;
ifMetagenerationNotMatch?: number;
}
type RestoreBucketResponse = [Bucket, unknown]; // [bucket, apiResponse]
// Restore soft-deleted bucket
const [restoredBucket] = await bucket.restore();
console.log('Bucket restored:', restoredBucket.name);
// Restore with preconditions
const [restoredBucket] = await bucket.restore({
ifMetagenerationMatch: bucket.metadata.metageneration
});
// Check if bucket is soft-deleted before restoring
const [exists] = await bucket.exists();
if (!exists && bucket.metadata.softDeleted) {
const [restoredBucket] = await bucket.restore();
console.log('Soft-deleted bucket restored successfully');
}request(options: RequestOptions): Promise<RequestResponse>
interface RequestOptions {
uri: string;
method?: string;
headers?: { [key: string]: string };
body?: any;
json?: boolean;
qs?: { [key: string]: string };
}
type RequestResponse = [any, unknown]; // [responseBody, rawResponse]
// Make custom authenticated request to Storage API
const [response] = await bucket.request({
uri: `/b/${bucket.name}/o`,
method: 'GET',
qs: {
prefix: 'logs/',
delimiter: '/'
}
});
// Custom POST request with body
const [response] = await bucket.request({
uri: `/b/${bucket.name}/acl`,
method: 'POST',
json: true,
body: {
entity: 'user-example@gmail.com',
role: 'READER'
}
});
// Use for advanced operations not covered by high-level methods
const [response] = await bucket.request({
uri: `/b/${bucket.name}`,
method: 'PATCH',
json: true,
body: {
labels: {
'custom-label': 'custom-value'
}
}
});All async methods support both Promise and callback patterns:
// Promise pattern (recommended)
const [files] = await bucket.getFiles();
// Callback pattern
bucket.getFiles((err, files, nextQuery, apiResponse) => {
if (err) {
console.error('Error:', err);
return;
}
console.log(`Found ${files.length} files`);
});