@google-cloud/storage
Version:
Cloud Storage Client Library for Node.js
1,266 lines (1,265 loc) • 141 kB
JavaScript
"use strict";
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Bucket = exports.BucketExceptionMessages = exports.AvailableServiceObjectMethods = exports.BucketActionToHTTPMethod = void 0;
const index_js_1 = require("./nodejs-common/index.js");
const paginator_1 = require("@google-cloud/paginator");
const promisify_1 = require("@google-cloud/promisify");
const fs = __importStar(require("fs"));
const mime_1 = __importDefault(require("mime"));
const path = __importStar(require("path"));
const p_limit_1 = __importDefault(require("p-limit"));
const util_1 = require("util");
const async_retry_1 = __importDefault(require("async-retry"));
const util_js_1 = require("./util.js");
const acl_js_1 = require("./acl.js");
const file_js_1 = require("./file.js");
const iam_js_1 = require("./iam.js");
const notification_js_1 = require("./notification.js");
const storage_js_1 = require("./storage.js");
const signer_js_1 = require("./signer.js");
const stream_1 = require("stream");
const url_1 = require("url");
var BucketActionToHTTPMethod;
(function (BucketActionToHTTPMethod) {
BucketActionToHTTPMethod["list"] = "GET";
})(BucketActionToHTTPMethod || (exports.BucketActionToHTTPMethod = BucketActionToHTTPMethod = {}));
var AvailableServiceObjectMethods;
(function (AvailableServiceObjectMethods) {
AvailableServiceObjectMethods[AvailableServiceObjectMethods["setMetadata"] = 0] = "setMetadata";
AvailableServiceObjectMethods[AvailableServiceObjectMethods["delete"] = 1] = "delete";
})(AvailableServiceObjectMethods || (exports.AvailableServiceObjectMethods = AvailableServiceObjectMethods = {}));
var BucketExceptionMessages;
(function (BucketExceptionMessages) {
BucketExceptionMessages["PROVIDE_SOURCE_FILE"] = "You must provide at least one source file.";
BucketExceptionMessages["DESTINATION_FILE_NOT_SPECIFIED"] = "A destination file must be specified.";
BucketExceptionMessages["CHANNEL_ID_REQUIRED"] = "An ID is required to create a channel.";
BucketExceptionMessages["TOPIC_NAME_REQUIRED"] = "A valid topic name is required.";
BucketExceptionMessages["CONFIGURATION_OBJECT_PREFIX_REQUIRED"] = "A configuration object with a prefix is required.";
BucketExceptionMessages["SPECIFY_FILE_NAME"] = "A file name must be specified.";
BucketExceptionMessages["METAGENERATION_NOT_PROVIDED"] = "A metageneration must be provided.";
BucketExceptionMessages["SUPPLY_NOTIFICATION_ID"] = "You must supply a notification ID.";
})(BucketExceptionMessages || (exports.BucketExceptionMessages = BucketExceptionMessages = {}));
/**
* @callback Crc32cGeneratorToStringCallback
* A method returning the CRC32C as a base64-encoded string.
*
* @returns {string}
*
* @example
* Hashing the string 'data' should return 'rth90Q=='
*
* ```js
* const buffer = Buffer.from('data');
* crc32c.update(buffer);
* crc32c.toString(); // 'rth90Q=='
* ```
**/
/**
* @callback Crc32cGeneratorValidateCallback
* A method validating a base64-encoded CRC32C string.
*
* @param {string} [value] base64-encoded CRC32C string to validate
* @returns {boolean}
*
* @example
* Should return `true` if the value matches, `false` otherwise
*
* ```js
* const buffer = Buffer.from('data');
* crc32c.update(buffer);
* crc32c.validate('DkjKuA=='); // false
* crc32c.validate('rth90Q=='); // true
* ```
**/
/**
* @callback Crc32cGeneratorUpdateCallback
* A method for passing `Buffer`s for CRC32C generation.
*
* @param {Buffer} [data] data to update CRC32C value with
* @returns {undefined}
*
* @example
* Hashing buffers from 'some ' and 'text\n'
*
* ```js
* const buffer1 = Buffer.from('some ');
* crc32c.update(buffer1);
*
* const buffer2 = Buffer.from('text\n');
* crc32c.update(buffer2);
*
* crc32c.toString(); // 'DkjKuA=='
* ```
**/
/**
* @typedef {object} CRC32CValidator
* @property {Crc32cGeneratorToStringCallback}
* @property {Crc32cGeneratorValidateCallback}
* @property {Crc32cGeneratorUpdateCallback}
*/
/**
* A function that generates a CRC32C Validator. Defaults to {@link CRC32C}
*
* @name Bucket#crc32cGenerator
* @type {CRC32CValidator}
*/
/**
* Get and set IAM policies for your bucket.
*
* @name Bucket#iam
* @mixes Iam
*
* See {@link https://cloud.google.com/storage/docs/access-control/iam#short_title_iam_management| Cloud Storage IAM Management}
* See {@link https://cloud.google.com/iam/docs/granting-changing-revoking-access| Granting, Changing, and Revoking Access}
* See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles}
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
*
* //-
* // Get the IAM policy for your bucket.
* //-
* bucket.iam.getPolicy(function(err, policy) {
* console.log(policy);
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.iam.getPolicy().then(function(data) {
* const policy = data[0];
* const apiResponse = data[1];
* });
*
* ```
* @example <caption>include:samples/iam.js</caption>
* region_tag:storage_view_bucket_iam_members
* Example of retrieving a bucket's IAM policy:
*
* @example <caption>include:samples/iam.js</caption>
* region_tag:storage_add_bucket_iam_member
* Example of adding to a bucket's IAM policy:
*
* @example <caption>include:samples/iam.js</caption>
* region_tag:storage_remove_bucket_iam_member
* Example of removing from a bucket's IAM policy:
*/
/**
* Cloud Storage uses access control lists (ACLs) to manage object and
* bucket access. ACLs are the mechanism you use to share objects with other
* users and allow other users to access your buckets and objects.
*
* An ACL consists of one or more entries, where each entry grants permissions
* to an entity. Permissions define the actions that can be performed against
* an object or bucket (for example, `READ` or `WRITE`); the entity defines
* who the permission applies to (for example, a specific user or group of
* users).
*
* The `acl` object on a Bucket instance provides methods to get you a list of
* the ACLs defined on your bucket, as well as set, update, and delete them.
*
* Buckets also have
* {@link https://cloud.google.com/storage/docs/access-control/lists#default| default ACLs}
* for all created files. Default ACLs specify permissions that all new
* objects added to the bucket will inherit by default. You can add, delete,
* get, and update entities and permissions for these as well with
* {@link Bucket#acl.default}.
*
* See {@link http://goo.gl/6qBBPO| About Access Control Lists}
* See {@link https://cloud.google.com/storage/docs/access-control/lists#default| Default ACLs}
*
* @name Bucket#acl
* @mixes Acl
* @property {Acl} default Cloud Storage Buckets have
* {@link https://cloud.google.com/storage/docs/access-control/lists#default| default ACLs}
* for all created files. You can add, delete, get, and update entities and
* permissions for these as well. The method signatures and examples are all
* the same, after only prefixing the method call with `default`.
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
*
* //-
* // Make a bucket's contents publicly readable.
* //-
* const myBucket = storage.bucket('my-bucket');
*
* const options = {
* entity: 'allUsers',
* role: storage.acl.READER_ROLE
* };
*
* myBucket.acl.add(options, function(err, aclObject) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* myBucket.acl.add(options).then(function(data) {
* const aclObject = data[0];
* const apiResponse = data[1];
* });
*
* ```
* @example <caption>include:samples/acl.js</caption>
* region_tag:storage_print_bucket_acl
* Example of printing a bucket's ACL:
*
* @example <caption>include:samples/acl.js</caption>
* region_tag:storage_print_bucket_acl_for_user
* Example of printing a bucket's ACL for a specific user:
*
* @example <caption>include:samples/acl.js</caption>
* region_tag:storage_add_bucket_owner
* Example of adding an owner to a bucket:
*
* @example <caption>include:samples/acl.js</caption>
* region_tag:storage_remove_bucket_owner
* Example of removing an owner from a bucket:
*
* @example <caption>include:samples/acl.js</caption>
* region_tag:storage_add_bucket_default_owner
* Example of adding a default owner to a bucket:
*
* @example <caption>include:samples/acl.js</caption>
* region_tag:storage_remove_bucket_default_owner
* Example of removing a default owner from a bucket:
*/
/**
* The API-formatted resource description of the bucket.
*
* Note: This is not guaranteed to be up-to-date when accessed. To get the
* latest record, call the `getMetadata()` method.
*
* @name Bucket#metadata
* @type {object}
*/
/**
* The bucket's name.
* @name Bucket#name
* @type {string}
*/
/**
* Get {@link File} objects for the files currently in the bucket as a
* readable object stream.
*
* @method Bucket#getFilesStream
* @param {GetFilesOptions} [query] Query object for listing files.
* @returns {ReadableStream} A readable stream that emits {@link File} instances.
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
*
* bucket.getFilesStream()
* .on('error', console.error)
* .on('data', function(file) {
* // file is a File object.
* })
* .on('end', function() {
* // All files retrieved.
* });
*
* //-
* // If you anticipate many results, you can end a stream early to prevent
* // unnecessary processing and API requests.
* //-
* bucket.getFilesStream()
* .on('data', function(file) {
* this.end();
* });
*
* //-
* // If you're filtering files with a delimiter, you should use
* // {@link Bucket#getFiles} and set `autoPaginate: false` in order to
* // preserve the `apiResponse` argument.
* //-
* const prefixes = [];
*
* function callback(err, files, nextQuery, apiResponse) {
* prefixes = prefixes.concat(apiResponse.prefixes);
*
* if (nextQuery) {
* bucket.getFiles(nextQuery, callback);
* } else {
* // prefixes = The finished array of prefixes.
* }
* }
*
* bucket.getFiles({
* autoPaginate: false,
* delimiter: '/'
* }, callback);
* ```
*/
/**
* Create a Bucket object to interact with a Cloud Storage bucket.
*
* @class
* @hideconstructor
*
* @param {Storage} storage A {@link Storage} instance.
* @param {string} name The name of the bucket.
* @param {object} [options] Configuration object.
* @param {string} [options.userProject] User project.
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
* ```
*/
class Bucket extends index_js_1.ServiceObject {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
getFilesStream(query) {
// placeholder body, overwritten in constructor
return new stream_1.Readable();
}
constructor(storage, name, options) {
var _a, _b, _c, _d;
options = options || {};
// Allow for "gs://"-style input, and strip any trailing slashes.
name = name.replace(/^gs:\/\//, '').replace(/\/+$/, '');
const requestQueryObject = {};
if ((_a = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) {
requestQueryObject.ifGenerationMatch =
options.preconditionOpts.ifGenerationMatch;
}
if ((_b = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationNotMatch) {
requestQueryObject.ifGenerationNotMatch =
options.preconditionOpts.ifGenerationNotMatch;
}
if ((_c = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _c === void 0 ? void 0 : _c.ifMetagenerationMatch) {
requestQueryObject.ifMetagenerationMatch =
options.preconditionOpts.ifMetagenerationMatch;
}
if ((_d = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _d === void 0 ? void 0 : _d.ifMetagenerationNotMatch) {
requestQueryObject.ifMetagenerationNotMatch =
options.preconditionOpts.ifMetagenerationNotMatch;
}
const userProject = options.userProject;
if (typeof userProject === 'string') {
requestQueryObject.userProject = userProject;
}
const methods = {
/**
* Create a bucket.
*
* @method Bucket#create
* @param {CreateBucketRequest} [metadata] Metadata to set for the bucket.
* @param {CreateBucketCallback} [callback] Callback function.
* @returns {Promise<CreateBucketResponse>}
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
* bucket.create(function(err, bucket, apiResponse) {
* if (!err) {
* // The bucket was created successfully.
* }
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.create().then(function(data) {
* const bucket = data[0];
* const apiResponse = data[1];
* });
* ```
*/
create: {
reqOpts: {
qs: requestQueryObject,
},
},
/**
* IamDeleteBucketOptions Configuration options.
* @property {boolean} [ignoreNotFound = false] Ignore an error if
* the bucket does not exist.
* @property {string} [userProject] The ID of the project which will be
* billed for the request.
*/
/**
* @typedef {array} DeleteBucketResponse
* @property {object} 0 The full API response.
*/
/**
* @callback DeleteBucketCallback
* @param {?Error} err Request error, if any.
* @param {object} apiResponse The full API response.
*/
/**
* Delete the bucket.
*
* See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/delete| Buckets: delete API Documentation}
*
* @method Bucket#delete
* @param {DeleteBucketOptions} [options] Configuration options.
* @param {boolean} [options.ignoreNotFound = false] Ignore an error if
* the bucket does not exist.
* @param {string} [options.userProject] The ID of the project which will be
* billed for the request.
* @param {DeleteBucketCallback} [callback] Callback function.
* @returns {Promise<DeleteBucketResponse>}
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
* bucket.delete(function(err, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.delete().then(function(data) {
* const apiResponse = data[0];
* });
*
* ```
* @example <caption>include:samples/buckets.js</caption>
* region_tag:storage_delete_bucket
* Another example:
*/
delete: {
reqOpts: {
qs: requestQueryObject,
},
},
/**
* @typedef {object} BucketExistsOptions Configuration options for Bucket#exists().
* @property {string} [userProject] The ID of the project which will be
* billed for the request.
*/
/**
* @typedef {array} BucketExistsResponse
* @property {boolean} 0 Whether the {@link Bucket} exists.
*/
/**
* @callback BucketExistsCallback
* @param {?Error} err Request error, if any.
* @param {boolean} exists Whether the {@link Bucket} exists.
*/
/**
* Check if the bucket exists.
*
* @method Bucket#exists
* @param {BucketExistsOptions} [options] Configuration options.
* @param {string} [options.userProject] The ID of the project which will be
* billed for the request.
* @param {BucketExistsCallback} [callback] Callback function.
* @returns {Promise<BucketExistsResponse>}
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
*
* bucket.exists(function(err, exists) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.exists().then(function(data) {
* const exists = data[0];
* });
* ```
*/
exists: {
reqOpts: {
qs: requestQueryObject,
},
},
/**
* @typedef {object} [GetBucketOptions] Configuration options for Bucket#get()
* @property {boolean} [autoCreate] Automatically create the object if
* it does not exist. Default: `false`
* @property {string} [userProject] The ID of the project which will be
* billed for the request.
*/
/**
* @typedef {array} GetBucketResponse
* @property {Bucket} 0 The {@link Bucket}.
* @property {object} 1 The full API response.
*/
/**
* @callback GetBucketCallback
* @param {?Error} err Request error, if any.
* @param {Bucket} bucket The {@link Bucket}.
* @param {object} apiResponse The full API response.
*/
/**
* Get a bucket if it exists.
*
* You may optionally use this to "get or create" an object by providing
* an object with `autoCreate` set to `true`. Any extra configuration that
* is normally required for the `create` method must be contained within
* this object as well.
*
* @method Bucket#get
* @param {GetBucketOptions} [options] Configuration options.
* @param {boolean} [options.autoCreate] Automatically create the object if
* it does not exist. Default: `false`
* @param {string} [options.userProject] The ID of the project which will be
* billed for the request.
* @param {GetBucketCallback} [callback] Callback function.
* @returns {Promise<GetBucketResponse>}
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
*
* bucket.get(function(err, bucket, apiResponse) {
* // `bucket.metadata` has been populated.
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.get().then(function(data) {
* const bucket = data[0];
* const apiResponse = data[1];
* });
* ```
*/
get: {
reqOpts: {
qs: requestQueryObject,
},
},
/**
* @typedef {array} GetBucketMetadataResponse
* @property {object} 0 The bucket metadata.
* @property {object} 1 The full API response.
*/
/**
* @callback GetBucketMetadataCallback
* @param {?Error} err Request error, if any.
* @param {object} metadata The bucket metadata.
* @param {object} apiResponse The full API response.
*/
/**
* @typedef {object} GetBucketMetadataOptions Configuration options for Bucket#getMetadata().
* @property {string} [userProject] The ID of the project which will be
* billed for the request.
*/
/**
* Get the bucket's metadata.
*
* To set metadata, see {@link Bucket#setMetadata}.
*
* See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/get| Buckets: get API Documentation}
*
* @method Bucket#getMetadata
* @param {GetBucketMetadataOptions} [options] Configuration options.
* @param {string} [options.userProject] The ID of the project which will be
* billed for the request.
* @param {GetBucketMetadataCallback} [callback] Callback function.
* @returns {Promise<GetBucketMetadataResponse>}
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
*
* bucket.getMetadata(function(err, metadata, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.getMetadata().then(function(data) {
* const metadata = data[0];
* const apiResponse = data[1];
* });
*
* ```
* @example <caption>include:samples/requesterPays.js</caption>
* region_tag:storage_get_requester_pays_status
* Example of retrieving the requester pays status of a bucket:
*/
getMetadata: {
reqOpts: {
qs: requestQueryObject,
},
},
/**
* @typedef {object} SetBucketMetadataOptions Configuration options for Bucket#setMetadata().
* @property {string} [userProject] The ID of the project which will be
* billed for the request.
*/
/**
* @typedef {array} SetBucketMetadataResponse
* @property {object} apiResponse The full API response.
*/
/**
* @callback SetBucketMetadataCallback
* @param {?Error} err Request error, if any.
* @param {object} metadata The bucket metadata.
*/
/**
* Set the bucket's metadata.
*
* See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation}
*
* @method Bucket#setMetadata
* @param {object<string, *>} metadata The metadata you wish to set.
* @param {SetBucketMetadataOptions} [options] Configuration options.
* @param {string} [options.userProject] The ID of the project which will be
* billed for the request.
* @param {SetBucketMetadataCallback} [callback] Callback function.
* @returns {Promise<SetBucketMetadataResponse>}
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
*
* //-
* // Set website metadata field on the bucket.
* //-
* const metadata = {
* website: {
* mainPageSuffix: 'http://example.com',
* notFoundPage: 'http://example.com/404.html'
* }
* };
*
* bucket.setMetadata(metadata, function(err, apiResponse) {});
*
* //-
* // Enable versioning for your bucket.
* //-
* bucket.setMetadata({
* versioning: {
* enabled: true
* }
* }, function(err, apiResponse) {});
*
* //-
* // Enable KMS encryption for objects within this bucket.
* //-
* bucket.setMetadata({
* encryption: {
* defaultKmsKeyName: 'projects/grape-spaceship-123/...'
* }
* }, function(err, apiResponse) {});
*
* //-
* // Set the default event-based hold value for new objects in this
* // bucket.
* //-
* bucket.setMetadata({
* defaultEventBasedHold: true
* }, function(err, apiResponse) {});
*
* //-
* // Remove object lifecycle rules.
* //-
* bucket.setMetadata({
* lifecycle: null
* }, function(err, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.setMetadata(metadata).then(function(data) {
* const apiResponse = data[0];
* });
* ```
*/
setMetadata: {
reqOpts: {
qs: requestQueryObject,
},
},
};
super({
parent: storage,
baseUrl: '/b',
id: name,
createMethod: storage.createBucket.bind(storage),
methods,
});
this.name = name;
this.storage = storage;
this.userProject = options.userProject;
this.acl = new acl_js_1.Acl({
request: this.request.bind(this),
pathPrefix: '/acl',
});
this.acl.default = new acl_js_1.Acl({
request: this.request.bind(this),
pathPrefix: '/defaultObjectAcl',
});
this.crc32cGenerator =
options.crc32cGenerator || this.storage.crc32cGenerator;
this.iam = new iam_js_1.Iam(this);
this.getFilesStream = paginator_1.paginator.streamify('getFiles');
this.instanceRetryValue = storage.retryOptions.autoRetry;
this.instancePreconditionOpts = options === null || options === void 0 ? void 0 : options.preconditionOpts;
}
/**
* The bucket's Cloud Storage URI (`gs://`)
*
* @example
* ```ts
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('my-bucket');
*
* // `gs://my-bucket`
* const href = bucket.cloudStorageURI.href;
* ```
*/
get cloudStorageURI() {
const uri = new url_1.URL('gs://');
uri.host = this.name;
return uri;
}
/**
* @typedef {object} AddLifecycleRuleOptions Configuration options for Bucket#addLifecycleRule().
* @property {boolean} [append=true] The new rules will be appended to any
* pre-existing rules.
*/
/**
*
* @typedef {object} LifecycleRule The new lifecycle rule to be added to objects
* in this bucket.
* @property {string|object} action The action to be taken upon matching of
* all the conditions 'delete', 'setStorageClass', or 'AbortIncompleteMultipartUpload'.
* **Note**: For configuring a raw-formatted rule object to be passed as `action`
* please refer to the [examples]{@link https://cloud.google.com/storage/docs/managing-lifecycles#configexamples}.
* @property {object} condition Condition a bucket must meet before the
* action occurs on the bucket. Refer to following supported [conditions]{@link https://cloud.google.com/storage/docs/lifecycle#conditions}.
* @property {string} [storageClass] When using the `setStorageClass`
* action, provide this option to dictate which storage class the object
* should update to. Please see
* [SetStorageClass option documentation]{@link https://cloud.google.com/storage/docs/lifecycle#setstorageclass} for supported transitions.
*/
/**
* Add an object lifecycle management rule to the bucket.
*
* By default, an Object Lifecycle Management rule provided to this method
* will be included to the existing policy. To replace all existing rules,
* supply the `options` argument, setting `append` to `false`.
*
* To add multiple rules, pass a list to the `rule` parameter. Calling this
* function multiple times asynchronously does not guarantee that all rules
* are added correctly.
*
* See {@link https://cloud.google.com/storage/docs/lifecycle| Object Lifecycle Management}
* See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation}
*
* @param {LifecycleRule|LifecycleRule[]} rule The new lifecycle rule or rules to be added to objects
* in this bucket.
* @param {string|object} rule.action The action to be taken upon matching of
* all the conditions 'delete', 'setStorageClass', or 'AbortIncompleteMultipartUpload'.
* **Note**: For configuring a raw-formatted rule object to be passed as `action`
* please refer to the [examples]{@link https://cloud.google.com/storage/docs/managing-lifecycles#configexamples}.
* @param {object} rule.condition Condition a bucket must meet before the
* action occurson the bucket. Refer to followitn supported [conditions]{@link https://cloud.google.com/storage/docs/lifecycle#conditions}.
* @param {string} [rule.storageClass] When using the `setStorageClass`
* action, provide this option to dictate which storage class the object
* should update to.
* @param {AddLifecycleRuleOptions} [options] Configuration object.
* @param {boolean} [options.append=true] Append the new rule to the existing
* policy.
* @param {SetBucketMetadataCallback} [callback] Callback function.
* @returns {Promise<SetBucketMetadataResponse>}
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
*
* //-
* // Automatically have an object deleted from this bucket once it is 3 years
* // of age.
* //-
* bucket.addLifecycleRule({
* action: 'delete',
* condition: {
* age: 365 * 3 // Specified in days.
* }
* }, function(err, apiResponse) {
* if (err) {
* // Error handling omitted.
* }
*
* const lifecycleRules = bucket.metadata.lifecycle.rule;
*
* // Iterate over the Object Lifecycle Management rules on this bucket.
* lifecycleRules.forEach(lifecycleRule => {});
* });
*
* //-
* // By default, the rule you provide will be added to the existing policy.
* // Optionally, you can disable this behavior to replace all of the
* // pre-existing rules.
* //-
* const options = {
* append: false
* };
*
* bucket.addLifecycleRule({
* action: 'delete',
* condition: {
* age: 365 * 3 // Specified in days.
* }
* }, options, function(err, apiResponse) {
* if (err) {
* // Error handling omitted.
* }
*
* // All rules have been replaced with the new "delete" rule.
*
* // Iterate over the Object Lifecycle Management rules on this bucket.
* lifecycleRules.forEach(lifecycleRule => {});
* });
*
* //-
* // For objects created before 2018, "downgrade" the storage class.
* //-
* bucket.addLifecycleRule({
* action: 'setStorageClass',
* storageClass: 'COLDLINE',
* condition: {
* createdBefore: new Date('2018')
* }
* }, function(err, apiResponse) {});
*
* //-
* // Delete objects created before 2016 which have the Coldline storage
* // class.
* //-
* bucket.addLifecycleRule({
* action: 'delete',
* condition: {
* matchesStorageClass: [
* 'COLDLINE'
* ],
* createdBefore: new Date('2016')
* }
* }, function(err, apiResponse) {});
*
* //-
* // Delete object that has a noncurrent timestamp that is at least 100 days.
* //-
* bucket.addLifecycleRule({
* action: 'delete',
* condition: {
* daysSinceNoncurrentTime: 100
* }
* }, function(err, apiResponse) {});
*
* //-
* // Delete object that has a noncurrent timestamp before 2020-01-01.
* //-
* bucket.addLifecycleRule({
* action: 'delete',
* condition: {
* noncurrentTimeBefore: new Date('2020-01-01')
* }
* }, function(err, apiResponse) {});
*
* //-
* // Delete object that has a customTime that is at least 100 days.
* //-
* bucket.addLifecycleRule({
* action: 'delete',
* condition: {
* daysSinceCustomTime: 100
* }
* }, function(err, apiResponse) ());
*
* //-
* // Delete object that has a customTime before 2020-01-01.
* //-
* bucket.addLifecycleRule({
* action: 'delete',
* condition: {
* customTimeBefore: new Date('2020-01-01')
* }
* }, function(err, apiResponse) {});
* ```
*/
addLifecycleRule(rule, optionsOrCallback, callback) {
let options = {};
if (typeof optionsOrCallback === 'function') {
callback = optionsOrCallback;
}
else if (optionsOrCallback) {
options = optionsOrCallback;
}
options = options || {};
const rules = Array.isArray(rule) ? rule : [rule];
for (const curRule of rules) {
if (curRule.condition.createdBefore instanceof Date) {
curRule.condition.createdBefore = curRule.condition.createdBefore
.toISOString()
.replace(/T.+$/, '');
}
if (curRule.condition.customTimeBefore instanceof Date) {
curRule.condition.customTimeBefore = curRule.condition.customTimeBefore
.toISOString()
.replace(/T.+$/, '');
}
if (curRule.condition.noncurrentTimeBefore instanceof Date) {
curRule.condition.noncurrentTimeBefore =
curRule.condition.noncurrentTimeBefore
.toISOString()
.replace(/T.+$/, '');
}
}
if (options.append === false) {
this.setMetadata({ lifecycle: { rule: rules } }, options, callback);
return;
}
// The default behavior appends the previously-defined lifecycle rules with
// the new ones just passed in by the user.
this.getMetadata((err, metadata) => {
var _a, _b;
if (err) {
callback(err);
return;
}
const currentLifecycleRules = Array.isArray((_a = metadata.lifecycle) === null || _a === void 0 ? void 0 : _a.rule)
? (_b = metadata.lifecycle) === null || _b === void 0 ? void 0 : _b.rule
: [];
this.setMetadata({
lifecycle: { rule: currentLifecycleRules.concat(rules) },
}, options, callback);
});
}
/**
* @typedef {object} CombineOptions
* @property {string} [kmsKeyName] Resource name of the Cloud KMS key, of
* the form
* `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`,
* that will be used to encrypt the object. Overwrites the object
* metadata's `kms_key_name` value, if any.
* @property {string} [userProject] The ID of the project which will be
* billed for the request.
*/
/**
* @callback CombineCallback
* @param {?Error} err Request error, if any.
* @param {File} newFile The new {@link File}.
* @param {object} apiResponse The full API response.
*/
/**
* @typedef {array} CombineResponse
* @property {File} 0 The new {@link File}.
* @property {object} 1 The full API response.
*/
/**
* Combine multiple files into one new file.
*
* See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/compose| Objects: compose API Documentation}
*
* @throws {Error} if a non-array is provided as sources argument.
* @throws {Error} if no sources are provided.
* @throws {Error} if no destination is provided.
*
* @param {string[]|File[]} sources The source files that will be
* combined.
* @param {string|File} destination The file you would like the
* source files combined into.
* @param {CombineOptions} [options] Configuration options.
* @param {string} [options.kmsKeyName] Resource name of the Cloud KMS key, of
* the form
* `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`,
* that will be used to encrypt the object. Overwrites the object
* metadata's `kms_key_name` value, if any.
* @param {string} [options.userProject] The ID of the project which will be
* billed for the request.
* @param {CombineCallback} [callback] Callback function.
* @returns {Promise<CombineResponse>}
*
* @example
* ```
* const logBucket = storage.bucket('log-bucket');
*
* const sources = [
* logBucket.file('2013-logs.txt'),
* logBucket.file('2014-logs.txt')
* ];
*
* const allLogs = logBucket.file('all-logs.txt');
*
* logBucket.combine(sources, allLogs, function(err, newFile, apiResponse) {
* // newFile === allLogs
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* logBucket.combine(sources, allLogs).then(function(data) {
* const newFile = data[0];
* const apiResponse = data[1];
* });
* ```
*/
combine(sources, destination, optionsOrCallback, callback) {
var _a;
if (!Array.isArray(sources) || sources.length === 0) {
throw new Error(BucketExceptionMessages.PROVIDE_SOURCE_FILE);
}
if (!destination) {
throw new Error(BucketExceptionMessages.DESTINATION_FILE_NOT_SPECIFIED);
}
let options = {};
if (typeof optionsOrCallback === 'function') {
callback = optionsOrCallback;
}
else if (optionsOrCallback) {
options = optionsOrCallback;
}
this.disableAutoRetryConditionallyIdempotent_(this.methods.setMetadata, // Not relevant but param is required
AvailableServiceObjectMethods.setMetadata, // Same as above
options);
const convertToFile = (file) => {
if (file instanceof file_js_1.File) {
return file;
}
return this.file(file);
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
sources = sources.map(convertToFile);
const destinationFile = convertToFile(destination);
callback = callback || index_js_1.util.noop;
if (!destinationFile.metadata.contentType) {
const destinationContentType = mime_1.default.getType(destinationFile.name) || undefined;
if (destinationContentType) {
destinationFile.metadata.contentType = destinationContentType;
}
}
let maxRetries = this.storage.retryOptions.maxRetries;
if ((((_a = destinationFile === null || destinationFile === void 0 ? void 0 : destinationFile.instancePreconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) ===
undefined &&
options.ifGenerationMatch === undefined &&
this.storage.retryOptions.idempotencyStrategy ===
storage_js_1.IdempotencyStrategy.RetryConditional) ||
this.storage.retryOptions.idempotencyStrategy ===
storage_js_1.IdempotencyStrategy.RetryNever) {
maxRetries = 0;
}
if (options.ifGenerationMatch === undefined) {
Object.assign(options, destinationFile.instancePreconditionOpts, options);
}
// Make the request from the destination File object.
destinationFile.request({
method: 'POST',
uri: '/compose',
maxRetries,
json: {
destination: {
contentType: destinationFile.metadata.contentType,
contentEncoding: destinationFile.metadata.contentEncoding,
},
sourceObjects: sources.map(source => {
const sourceObject = {
name: source.name,
};
if (source.metadata && source.metadata.generation) {
sourceObject.generation = parseInt(source.metadata.generation.toString());
}
return sourceObject;
}),
},
qs: options,
}, (err, resp) => {
this.storage.retryOptions.autoRetry = this.instanceRetryValue;
if (err) {
callback(err, null, resp);
return;
}
callback(null, destinationFile, resp);
});
}
/**
* See a {@link https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll| Objects: watchAll request body}.
*
* @typedef {object} CreateChannelConfig
* @property {string} address The address where notifications are
* delivered for this channel.
* @property {string} [delimiter] Returns results in a directory-like mode.
* @property {number} [maxResults] Maximum number of `items` plus `prefixes`
* to return in a single page of responses.
* @property {string} [pageToken] A previously-returned page token
* representing part of the larger set of results to view.
* @property {string} [prefix] Filter results to objects whose names begin
* with this prefix.
* @property {string} [projection=noAcl] Set of properties to return.
* @property {string} [userProject] The ID of the project which will be
* billed for the request.
* @property {boolean} [versions=false] If `true`, lists all versions of an object
* as distinct results.
*/
/**
* @typedef {object} CreateChannelOptions
* @property {string} [userProject] The ID of the project which will be
* billed for the request.
*/
/**
* @typedef {array} CreateChannelResponse
* @property {Channel} 0 The new {@link Channel}.
* @property {object} 1 The full API response.
*/
/**
* @callback CreateChannelCallback
* @param {?Error} err Request error, if any.
* @param {Channel} channel The new {@link Channel}.
* @param {object} apiResponse The full API response.
*/
/**
* Create a channel that will be notified when objects in this bucket changes.
*
* @throws {Error} If an ID is not provided.
* @throws {Error} If an address is not provided.
*
* See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll| Objects: watchAll API Documentation}
*
* @param {string} id The ID of the channel to create.
* @param {CreateChannelConfig} config Configuration for creating channel.
* @param {string} config.address The address where notifications are
* delivered for this channel.
* @param {string} [config.delimiter] Returns results in a directory-like mode.
* @param {number} [config.maxResults] Maximum number of `items` plus `prefixes`
* to return in a single page of responses.
* @param {string} [config.pageToken] A previously-returned page token
* representing part of the larger set of results to view.
* @param {string} [config.prefix] Filter results to objects whose names begin
* with this prefix.
* @param {string} [config.projection=noAcl] Set of properties to return.
* @param {string} [config.userProject] The ID of the project which will be
* billed for the request.
* @param {boolean} [config.versions=false] If `true`, lists all versions of an object
* as distinct results.
* @param {CreateChannelOptions} [options] Configuration options.
* @param {string} [options.userProject] The ID of the project which will be
* billed for the request.
* @param {CreateChannelCallback} [callback] Callback function.
* @returns {Promise<CreateChannelResponse>}
*
* @example
* ```
* const {Storage} = require('@google-cloud/storage');
* const storage = new Storage();
* const bucket = storage.bucket('albums');
* const id = 'new-channel-id';
*
* const config = {
* address: 'https://...'
* };
*
* bucket.createChannel(id, config, function(err, channel, apiResponse) {
* if (!err) {
* // Channel created successfully.
* }
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.createChannel(id, config).then(function(data) {
* const channel = data[0];
* const apiResponse = data[1];
* });
* ```
*/
createChannel(id, config, optionsOrCallback, callback) {
if (typeof id !== 'string') {
throw new Error(BucketExceptionMessages.CHANNEL_ID_REQUIRED);
}
let options = {};
if (typeof optionsOrCallback === 'function') {
callback = optionsOrCallback;
}
else if (optionsOrCallback) {
options = optionsOrCallback;
}
this.request({
method: 'POST',
uri: '/o/watch',
json: Object.assign({
id,
type: 'web_hook',
}, config),
qs: options,
}, (err, apiResponse) => {
if (err) {
callback(err, null, apiResponse);
return;
}
const resourceId = apiResponse.resourceId;
const channel = this.storage.channel(id, resourceId);
channel.metadata = apiResponse;
callback(null, channel, apiResponse);
});
}
/**
* Metadata to set for the Notification.
*
* @typedef {object} CreateNotificationOptions
* @property {object} [customAttributes] An optional list of additional
* attributes to attach to each Cloud PubSub message published for this
* notification subscription.
* @property {string[]} [eventTypes] If present, only send notifications about
* listed event types. If empty, sent notifications for all event types.
* @property {string} [objectNamePrefix