UNPKG

@google-cloud/storage

Version:
1,266 lines (1,265 loc) 141 kB
"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