UNPKG

139 kBJavaScriptView Raw
1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14import { ServiceObject, util, } from './nodejs-common/index.js';
15import { paginator } from '@google-cloud/paginator';
16import { promisifyAll } from '@google-cloud/promisify';
17import * as fs from 'fs';
18import mime from 'mime';
19import * as path from 'path';
20import pLimit from 'p-limit';
21import { promisify } from 'util';
22import AsyncRetry from 'async-retry';
23import { convertObjKeysToSnakeCase } from './util.js';
24import { Acl } from './acl.js';
25import { File, } from './file.js';
26import { Iam } from './iam.js';
27import { Notification } from './notification.js';
28import { IdempotencyStrategy, } from './storage.js';
29import { URLSigner, } from './signer.js';
30import { Readable } from 'stream';
31import { URL } from 'url';
32export var BucketActionToHTTPMethod;
33(function (BucketActionToHTTPMethod) {
34 BucketActionToHTTPMethod["list"] = "GET";
35})(BucketActionToHTTPMethod || (BucketActionToHTTPMethod = {}));
36export var AvailableServiceObjectMethods;
37(function (AvailableServiceObjectMethods) {
38 AvailableServiceObjectMethods[AvailableServiceObjectMethods["setMetadata"] = 0] = "setMetadata";
39 AvailableServiceObjectMethods[AvailableServiceObjectMethods["delete"] = 1] = "delete";
40})(AvailableServiceObjectMethods || (AvailableServiceObjectMethods = {}));
41export var BucketExceptionMessages;
42(function (BucketExceptionMessages) {
43 BucketExceptionMessages["PROVIDE_SOURCE_FILE"] = "You must provide at least one source file.";
44 BucketExceptionMessages["DESTINATION_FILE_NOT_SPECIFIED"] = "A destination file must be specified.";
45 BucketExceptionMessages["CHANNEL_ID_REQUIRED"] = "An ID is required to create a channel.";
46 BucketExceptionMessages["TOPIC_NAME_REQUIRED"] = "A valid topic name is required.";
47 BucketExceptionMessages["CONFIGURATION_OBJECT_PREFIX_REQUIRED"] = "A configuration object with a prefix is required.";
48 BucketExceptionMessages["SPECIFY_FILE_NAME"] = "A file name must be specified.";
49 BucketExceptionMessages["METAGENERATION_NOT_PROVIDED"] = "A metageneration must be provided.";
50 BucketExceptionMessages["SUPPLY_NOTIFICATION_ID"] = "You must supply a notification ID.";
51})(BucketExceptionMessages || (BucketExceptionMessages = {}));
52/**
53 * @callback Crc32cGeneratorToStringCallback
54 * A method returning the CRC32C as a base64-encoded string.
55 *
56 * @returns {string}
57 *
58 * @example
59 * Hashing the string 'data' should return 'rth90Q=='
60 *
61 * ```js
62 * const buffer = Buffer.from('data');
63 * crc32c.update(buffer);
64 * crc32c.toString(); // 'rth90Q=='
65 * ```
66 **/
67/**
68 * @callback Crc32cGeneratorValidateCallback
69 * A method validating a base64-encoded CRC32C string.
70 *
71 * @param {string} [value] base64-encoded CRC32C string to validate
72 * @returns {boolean}
73 *
74 * @example
75 * Should return `true` if the value matches, `false` otherwise
76 *
77 * ```js
78 * const buffer = Buffer.from('data');
79 * crc32c.update(buffer);
80 * crc32c.validate('DkjKuA=='); // false
81 * crc32c.validate('rth90Q=='); // true
82 * ```
83 **/
84/**
85 * @callback Crc32cGeneratorUpdateCallback
86 * A method for passing `Buffer`s for CRC32C generation.
87 *
88 * @param {Buffer} [data] data to update CRC32C value with
89 * @returns {undefined}
90 *
91 * @example
92 * Hashing buffers from 'some ' and 'text\n'
93 *
94 * ```js
95 * const buffer1 = Buffer.from('some ');
96 * crc32c.update(buffer1);
97 *
98 * const buffer2 = Buffer.from('text\n');
99 * crc32c.update(buffer2);
100 *
101 * crc32c.toString(); // 'DkjKuA=='
102 * ```
103 **/
104/**
105 * @typedef {object} CRC32CValidator
106 * @property {Crc32cGeneratorToStringCallback}
107 * @property {Crc32cGeneratorValidateCallback}
108 * @property {Crc32cGeneratorUpdateCallback}
109 */
110/**
111 * A function that generates a CRC32C Validator. Defaults to {@link CRC32C}
112 *
113 * @name Bucket#crc32cGenerator
114 * @type {CRC32CValidator}
115 */
116/**
117 * Get and set IAM policies for your bucket.
118 *
119 * @name Bucket#iam
120 * @mixes Iam
121 *
122 * See {@link https://cloud.google.com/storage/docs/access-control/iam#short_title_iam_management| Cloud Storage IAM Management}
123 * See {@link https://cloud.google.com/iam/docs/granting-changing-revoking-access| Granting, Changing, and Revoking Access}
124 * See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles}
125 *
126 * @example
127 * ```
128 * const {Storage} = require('@google-cloud/storage');
129 * const storage = new Storage();
130 * const bucket = storage.bucket('albums');
131 *
132 * //-
133 * // Get the IAM policy for your bucket.
134 * //-
135 * bucket.iam.getPolicy(function(err, policy) {
136 * console.log(policy);
137 * });
138 *
139 * //-
140 * // If the callback is omitted, we'll return a Promise.
141 * //-
142 * bucket.iam.getPolicy().then(function(data) {
143 * const policy = data[0];
144 * const apiResponse = data[1];
145 * });
146 *
147 * ```
148 * @example <caption>include:samples/iam.js</caption>
149 * region_tag:storage_view_bucket_iam_members
150 * Example of retrieving a bucket's IAM policy:
151 *
152 * @example <caption>include:samples/iam.js</caption>
153 * region_tag:storage_add_bucket_iam_member
154 * Example of adding to a bucket's IAM policy:
155 *
156 * @example <caption>include:samples/iam.js</caption>
157 * region_tag:storage_remove_bucket_iam_member
158 * Example of removing from a bucket's IAM policy:
159 */
160/**
161 * Cloud Storage uses access control lists (ACLs) to manage object and
162 * bucket access. ACLs are the mechanism you use to share objects with other
163 * users and allow other users to access your buckets and objects.
164 *
165 * An ACL consists of one or more entries, where each entry grants permissions
166 * to an entity. Permissions define the actions that can be performed against
167 * an object or bucket (for example, `READ` or `WRITE`); the entity defines
168 * who the permission applies to (for example, a specific user or group of
169 * users).
170 *
171 * The `acl` object on a Bucket instance provides methods to get you a list of
172 * the ACLs defined on your bucket, as well as set, update, and delete them.
173 *
174 * Buckets also have
175 * {@link https://cloud.google.com/storage/docs/access-control/lists#default| default ACLs}
176 * for all created files. Default ACLs specify permissions that all new
177 * objects added to the bucket will inherit by default. You can add, delete,
178 * get, and update entities and permissions for these as well with
179 * {@link Bucket#acl.default}.
180 *
181 * See {@link http://goo.gl/6qBBPO| About Access Control Lists}
182 * See {@link https://cloud.google.com/storage/docs/access-control/lists#default| Default ACLs}
183 *
184 * @name Bucket#acl
185 * @mixes Acl
186 * @property {Acl} default Cloud Storage Buckets have
187 * {@link https://cloud.google.com/storage/docs/access-control/lists#default| default ACLs}
188 * for all created files. You can add, delete, get, and update entities and
189 * permissions for these as well. The method signatures and examples are all
190 * the same, after only prefixing the method call with `default`.
191 *
192 * @example
193 * ```
194 * const {Storage} = require('@google-cloud/storage');
195 * const storage = new Storage();
196 *
197 * //-
198 * // Make a bucket's contents publicly readable.
199 * //-
200 * const myBucket = storage.bucket('my-bucket');
201 *
202 * const options = {
203 * entity: 'allUsers',
204 * role: storage.acl.READER_ROLE
205 * };
206 *
207 * myBucket.acl.add(options, function(err, aclObject) {});
208 *
209 * //-
210 * // If the callback is omitted, we'll return a Promise.
211 * //-
212 * myBucket.acl.add(options).then(function(data) {
213 * const aclObject = data[0];
214 * const apiResponse = data[1];
215 * });
216 *
217 * ```
218 * @example <caption>include:samples/acl.js</caption>
219 * region_tag:storage_print_bucket_acl
220 * Example of printing a bucket's ACL:
221 *
222 * @example <caption>include:samples/acl.js</caption>
223 * region_tag:storage_print_bucket_acl_for_user
224 * Example of printing a bucket's ACL for a specific user:
225 *
226 * @example <caption>include:samples/acl.js</caption>
227 * region_tag:storage_add_bucket_owner
228 * Example of adding an owner to a bucket:
229 *
230 * @example <caption>include:samples/acl.js</caption>
231 * region_tag:storage_remove_bucket_owner
232 * Example of removing an owner from a bucket:
233 *
234 * @example <caption>include:samples/acl.js</caption>
235 * region_tag:storage_add_bucket_default_owner
236 * Example of adding a default owner to a bucket:
237 *
238 * @example <caption>include:samples/acl.js</caption>
239 * region_tag:storage_remove_bucket_default_owner
240 * Example of removing a default owner from a bucket:
241 */
242/**
243 * The API-formatted resource description of the bucket.
244 *
245 * Note: This is not guaranteed to be up-to-date when accessed. To get the
246 * latest record, call the `getMetadata()` method.
247 *
248 * @name Bucket#metadata
249 * @type {object}
250 */
251/**
252 * The bucket's name.
253 * @name Bucket#name
254 * @type {string}
255 */
256/**
257 * Get {@link File} objects for the files currently in the bucket as a
258 * readable object stream.
259 *
260 * @method Bucket#getFilesStream
261 * @param {GetFilesOptions} [query] Query object for listing files.
262 * @returns {ReadableStream} A readable stream that emits {@link File} instances.
263 *
264 * @example
265 * ```
266 * const {Storage} = require('@google-cloud/storage');
267 * const storage = new Storage();
268 * const bucket = storage.bucket('albums');
269 *
270 * bucket.getFilesStream()
271 * .on('error', console.error)
272 * .on('data', function(file) {
273 * // file is a File object.
274 * })
275 * .on('end', function() {
276 * // All files retrieved.
277 * });
278 *
279 * //-
280 * // If you anticipate many results, you can end a stream early to prevent
281 * // unnecessary processing and API requests.
282 * //-
283 * bucket.getFilesStream()
284 * .on('data', function(file) {
285 * this.end();
286 * });
287 *
288 * //-
289 * // If you're filtering files with a delimiter, you should use
290 * // {@link Bucket#getFiles} and set `autoPaginate: false` in order to
291 * // preserve the `apiResponse` argument.
292 * //-
293 * const prefixes = [];
294 *
295 * function callback(err, files, nextQuery, apiResponse) {
296 * prefixes = prefixes.concat(apiResponse.prefixes);
297 *
298 * if (nextQuery) {
299 * bucket.getFiles(nextQuery, callback);
300 * } else {
301 * // prefixes = The finished array of prefixes.
302 * }
303 * }
304 *
305 * bucket.getFiles({
306 * autoPaginate: false,
307 * delimiter: '/'
308 * }, callback);
309 * ```
310 */
311/**
312 * Create a Bucket object to interact with a Cloud Storage bucket.
313 *
314 * @class
315 * @hideconstructor
316 *
317 * @param {Storage} storage A {@link Storage} instance.
318 * @param {string} name The name of the bucket.
319 * @param {object} [options] Configuration object.
320 * @param {string} [options.userProject] User project.
321 *
322 * @example
323 * ```
324 * const {Storage} = require('@google-cloud/storage');
325 * const storage = new Storage();
326 * const bucket = storage.bucket('albums');
327 * ```
328 */
329class Bucket extends ServiceObject {
330 // eslint-disable-next-line @typescript-eslint/no-unused-vars
331 getFilesStream(query) {
332 // placeholder body, overwritten in constructor
333 return new Readable();
334 }
335 constructor(storage, name, options) {
336 var _a, _b, _c, _d;
337 options = options || {};
338 // Allow for "gs://"-style input, and strip any trailing slashes.
339 name = name.replace(/^gs:\/\//, '').replace(/\/+$/, '');
340 const requestQueryObject = {};
341 if ((_a = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) {
342 requestQueryObject.ifGenerationMatch =
343 options.preconditionOpts.ifGenerationMatch;
344 }
345 if ((_b = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationNotMatch) {
346 requestQueryObject.ifGenerationNotMatch =
347 options.preconditionOpts.ifGenerationNotMatch;
348 }
349 if ((_c = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _c === void 0 ? void 0 : _c.ifMetagenerationMatch) {
350 requestQueryObject.ifMetagenerationMatch =
351 options.preconditionOpts.ifMetagenerationMatch;
352 }
353 if ((_d = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _d === void 0 ? void 0 : _d.ifMetagenerationNotMatch) {
354 requestQueryObject.ifMetagenerationNotMatch =
355 options.preconditionOpts.ifMetagenerationNotMatch;
356 }
357 const userProject = options.userProject;
358 if (typeof userProject === 'string') {
359 requestQueryObject.userProject = userProject;
360 }
361 const methods = {
362 /**
363 * Create a bucket.
364 *
365 * @method Bucket#create
366 * @param {CreateBucketRequest} [metadata] Metadata to set for the bucket.
367 * @param {CreateBucketCallback} [callback] Callback function.
368 * @returns {Promise<CreateBucketResponse>}
369 *
370 * @example
371 * ```
372 * const {Storage} = require('@google-cloud/storage');
373 * const storage = new Storage();
374 * const bucket = storage.bucket('albums');
375 * bucket.create(function(err, bucket, apiResponse) {
376 * if (!err) {
377 * // The bucket was created successfully.
378 * }
379 * });
380 *
381 * //-
382 * // If the callback is omitted, we'll return a Promise.
383 * //-
384 * bucket.create().then(function(data) {
385 * const bucket = data[0];
386 * const apiResponse = data[1];
387 * });
388 * ```
389 */
390 create: {
391 reqOpts: {
392 qs: requestQueryObject,
393 },
394 },
395 /**
396 * IamDeleteBucketOptions Configuration options.
397 * @property {boolean} [ignoreNotFound = false] Ignore an error if
398 * the bucket does not exist.
399 * @property {string} [userProject] The ID of the project which will be
400 * billed for the request.
401 */
402 /**
403 * @typedef {array} DeleteBucketResponse
404 * @property {object} 0 The full API response.
405 */
406 /**
407 * @callback DeleteBucketCallback
408 * @param {?Error} err Request error, if any.
409 * @param {object} apiResponse The full API response.
410 */
411 /**
412 * Delete the bucket.
413 *
414 * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/delete| Buckets: delete API Documentation}
415 *
416 * @method Bucket#delete
417 * @param {DeleteBucketOptions} [options] Configuration options.
418 * @param {boolean} [options.ignoreNotFound = false] Ignore an error if
419 * the bucket does not exist.
420 * @param {string} [options.userProject] The ID of the project which will be
421 * billed for the request.
422 * @param {DeleteBucketCallback} [callback] Callback function.
423 * @returns {Promise<DeleteBucketResponse>}
424 *
425 * @example
426 * ```
427 * const {Storage} = require('@google-cloud/storage');
428 * const storage = new Storage();
429 * const bucket = storage.bucket('albums');
430 * bucket.delete(function(err, apiResponse) {});
431 *
432 * //-
433 * // If the callback is omitted, we'll return a Promise.
434 * //-
435 * bucket.delete().then(function(data) {
436 * const apiResponse = data[0];
437 * });
438 *
439 * ```
440 * @example <caption>include:samples/buckets.js</caption>
441 * region_tag:storage_delete_bucket
442 * Another example:
443 */
444 delete: {
445 reqOpts: {
446 qs: requestQueryObject,
447 },
448 },
449 /**
450 * @typedef {object} BucketExistsOptions Configuration options for Bucket#exists().
451 * @property {string} [userProject] The ID of the project which will be
452 * billed for the request.
453 */
454 /**
455 * @typedef {array} BucketExistsResponse
456 * @property {boolean} 0 Whether the {@link Bucket} exists.
457 */
458 /**
459 * @callback BucketExistsCallback
460 * @param {?Error} err Request error, if any.
461 * @param {boolean} exists Whether the {@link Bucket} exists.
462 */
463 /**
464 * Check if the bucket exists.
465 *
466 * @method Bucket#exists
467 * @param {BucketExistsOptions} [options] Configuration options.
468 * @param {string} [options.userProject] The ID of the project which will be
469 * billed for the request.
470 * @param {BucketExistsCallback} [callback] Callback function.
471 * @returns {Promise<BucketExistsResponse>}
472 *
473 * @example
474 * ```
475 * const {Storage} = require('@google-cloud/storage');
476 * const storage = new Storage();
477 * const bucket = storage.bucket('albums');
478 *
479 * bucket.exists(function(err, exists) {});
480 *
481 * //-
482 * // If the callback is omitted, we'll return a Promise.
483 * //-
484 * bucket.exists().then(function(data) {
485 * const exists = data[0];
486 * });
487 * ```
488 */
489 exists: {
490 reqOpts: {
491 qs: requestQueryObject,
492 },
493 },
494 /**
495 * @typedef {object} [GetBucketOptions] Configuration options for Bucket#get()
496 * @property {boolean} [autoCreate] Automatically create the object if
497 * it does not exist. Default: `false`
498 * @property {string} [userProject] The ID of the project which will be
499 * billed for the request.
500 */
501 /**
502 * @typedef {array} GetBucketResponse
503 * @property {Bucket} 0 The {@link Bucket}.
504 * @property {object} 1 The full API response.
505 */
506 /**
507 * @callback GetBucketCallback
508 * @param {?Error} err Request error, if any.
509 * @param {Bucket} bucket The {@link Bucket}.
510 * @param {object} apiResponse The full API response.
511 */
512 /**
513 * Get a bucket if it exists.
514 *
515 * You may optionally use this to "get or create" an object by providing
516 * an object with `autoCreate` set to `true`. Any extra configuration that
517 * is normally required for the `create` method must be contained within
518 * this object as well.
519 *
520 * @method Bucket#get
521 * @param {GetBucketOptions} [options] Configuration options.
522 * @param {boolean} [options.autoCreate] Automatically create the object if
523 * it does not exist. Default: `false`
524 * @param {string} [options.userProject] The ID of the project which will be
525 * billed for the request.
526 * @param {GetBucketCallback} [callback] Callback function.
527 * @returns {Promise<GetBucketResponse>}
528 *
529 * @example
530 * ```
531 * const {Storage} = require('@google-cloud/storage');
532 * const storage = new Storage();
533 * const bucket = storage.bucket('albums');
534 *
535 * bucket.get(function(err, bucket, apiResponse) {
536 * // `bucket.metadata` has been populated.
537 * });
538 *
539 * //-
540 * // If the callback is omitted, we'll return a Promise.
541 * //-
542 * bucket.get().then(function(data) {
543 * const bucket = data[0];
544 * const apiResponse = data[1];
545 * });
546 * ```
547 */
548 get: {
549 reqOpts: {
550 qs: requestQueryObject,
551 },
552 },
553 /**
554 * @typedef {array} GetBucketMetadataResponse
555 * @property {object} 0 The bucket metadata.
556 * @property {object} 1 The full API response.
557 */
558 /**
559 * @callback GetBucketMetadataCallback
560 * @param {?Error} err Request error, if any.
561 * @param {object} metadata The bucket metadata.
562 * @param {object} apiResponse The full API response.
563 */
564 /**
565 * @typedef {object} GetBucketMetadataOptions Configuration options for Bucket#getMetadata().
566 * @property {string} [userProject] The ID of the project which will be
567 * billed for the request.
568 */
569 /**
570 * Get the bucket's metadata.
571 *
572 * To set metadata, see {@link Bucket#setMetadata}.
573 *
574 * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/get| Buckets: get API Documentation}
575 *
576 * @method Bucket#getMetadata
577 * @param {GetBucketMetadataOptions} [options] Configuration options.
578 * @param {string} [options.userProject] The ID of the project which will be
579 * billed for the request.
580 * @param {GetBucketMetadataCallback} [callback] Callback function.
581 * @returns {Promise<GetBucketMetadataResponse>}
582 *
583 * @example
584 * ```
585 * const {Storage} = require('@google-cloud/storage');
586 * const storage = new Storage();
587 * const bucket = storage.bucket('albums');
588 *
589 * bucket.getMetadata(function(err, metadata, apiResponse) {});
590 *
591 * //-
592 * // If the callback is omitted, we'll return a Promise.
593 * //-
594 * bucket.getMetadata().then(function(data) {
595 * const metadata = data[0];
596 * const apiResponse = data[1];
597 * });
598 *
599 * ```
600 * @example <caption>include:samples/requesterPays.js</caption>
601 * region_tag:storage_get_requester_pays_status
602 * Example of retrieving the requester pays status of a bucket:
603 */
604 getMetadata: {
605 reqOpts: {
606 qs: requestQueryObject,
607 },
608 },
609 /**
610 * @typedef {object} SetBucketMetadataOptions Configuration options for Bucket#setMetadata().
611 * @property {string} [userProject] The ID of the project which will be
612 * billed for the request.
613 */
614 /**
615 * @typedef {array} SetBucketMetadataResponse
616 * @property {object} apiResponse The full API response.
617 */
618 /**
619 * @callback SetBucketMetadataCallback
620 * @param {?Error} err Request error, if any.
621 * @param {object} metadata The bucket metadata.
622 */
623 /**
624 * Set the bucket's metadata.
625 *
626 * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation}
627 *
628 * @method Bucket#setMetadata
629 * @param {object<string, *>} metadata The metadata you wish to set.
630 * @param {SetBucketMetadataOptions} [options] Configuration options.
631 * @param {string} [options.userProject] The ID of the project which will be
632 * billed for the request.
633 * @param {SetBucketMetadataCallback} [callback] Callback function.
634 * @returns {Promise<SetBucketMetadataResponse>}
635 *
636 * @example
637 * ```
638 * const {Storage} = require('@google-cloud/storage');
639 * const storage = new Storage();
640 * const bucket = storage.bucket('albums');
641 *
642 * //-
643 * // Set website metadata field on the bucket.
644 * //-
645 * const metadata = {
646 * website: {
647 * mainPageSuffix: 'http://example.com',
648 * notFoundPage: 'http://example.com/404.html'
649 * }
650 * };
651 *
652 * bucket.setMetadata(metadata, function(err, apiResponse) {});
653 *
654 * //-
655 * // Enable versioning for your bucket.
656 * //-
657 * bucket.setMetadata({
658 * versioning: {
659 * enabled: true
660 * }
661 * }, function(err, apiResponse) {});
662 *
663 * //-
664 * // Enable KMS encryption for objects within this bucket.
665 * //-
666 * bucket.setMetadata({
667 * encryption: {
668 * defaultKmsKeyName: 'projects/grape-spaceship-123/...'
669 * }
670 * }, function(err, apiResponse) {});
671 *
672 * //-
673 * // Set the default event-based hold value for new objects in this
674 * // bucket.
675 * //-
676 * bucket.setMetadata({
677 * defaultEventBasedHold: true
678 * }, function(err, apiResponse) {});
679 *
680 * //-
681 * // Remove object lifecycle rules.
682 * //-
683 * bucket.setMetadata({
684 * lifecycle: null
685 * }, function(err, apiResponse) {});
686 *
687 * //-
688 * // If the callback is omitted, we'll return a Promise.
689 * //-
690 * bucket.setMetadata(metadata).then(function(data) {
691 * const apiResponse = data[0];
692 * });
693 * ```
694 */
695 setMetadata: {
696 reqOpts: {
697 qs: requestQueryObject,
698 },
699 },
700 };
701 super({
702 parent: storage,
703 baseUrl: '/b',
704 id: name,
705 createMethod: storage.createBucket.bind(storage),
706 methods,
707 });
708 this.name = name;
709 this.storage = storage;
710 this.userProject = options.userProject;
711 this.acl = new Acl({
712 request: this.request.bind(this),
713 pathPrefix: '/acl',
714 });
715 this.acl.default = new Acl({
716 request: this.request.bind(this),
717 pathPrefix: '/defaultObjectAcl',
718 });
719 this.crc32cGenerator =
720 options.crc32cGenerator || this.storage.crc32cGenerator;
721 this.iam = new Iam(this);
722 this.getFilesStream = paginator.streamify('getFiles');
723 this.instanceRetryValue = storage.retryOptions.autoRetry;
724 this.instancePreconditionOpts = options === null || options === void 0 ? void 0 : options.preconditionOpts;
725 }
726 /**
727 * The bucket's Cloud Storage URI (`gs://`)
728 *
729 * @example
730 * ```ts
731 * const {Storage} = require('@google-cloud/storage');
732 * const storage = new Storage();
733 * const bucket = storage.bucket('my-bucket');
734 *
735 * // `gs://my-bucket`
736 * const href = bucket.cloudStorageURI.href;
737 * ```
738 */
739 get cloudStorageURI() {
740 const uri = new URL('gs://');
741 uri.host = this.name;
742 return uri;
743 }
744 /**
745 * @typedef {object} AddLifecycleRuleOptions Configuration options for Bucket#addLifecycleRule().
746 * @property {boolean} [append=true] The new rules will be appended to any
747 * pre-existing rules.
748 */
749 /**
750 *
751 * @typedef {object} LifecycleRule The new lifecycle rule to be added to objects
752 * in this bucket.
753 * @property {string|object} action The action to be taken upon matching of
754 * all the conditions 'delete', 'setStorageClass', or 'AbortIncompleteMultipartUpload'.
755 * **Note**: For configuring a raw-formatted rule object to be passed as `action`
756 * please refer to the [examples]{@link https://cloud.google.com/storage/docs/managing-lifecycles#configexamples}.
757 * @property {object} condition Condition a bucket must meet before the
758 * action occurs on the bucket. Refer to following supported [conditions]{@link https://cloud.google.com/storage/docs/lifecycle#conditions}.
759 * @property {string} [storageClass] When using the `setStorageClass`
760 * action, provide this option to dictate which storage class the object
761 * should update to. Please see
762 * [SetStorageClass option documentation]{@link https://cloud.google.com/storage/docs/lifecycle#setstorageclass} for supported transitions.
763 */
764 /**
765 * Add an object lifecycle management rule to the bucket.
766 *
767 * By default, an Object Lifecycle Management rule provided to this method
768 * will be included to the existing policy. To replace all existing rules,
769 * supply the `options` argument, setting `append` to `false`.
770 *
771 * To add multiple rules, pass a list to the `rule` parameter. Calling this
772 * function multiple times asynchronously does not guarantee that all rules
773 * are added correctly.
774 *
775 * See {@link https://cloud.google.com/storage/docs/lifecycle| Object Lifecycle Management}
776 * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation}
777 *
778 * @param {LifecycleRule|LifecycleRule[]} rule The new lifecycle rule or rules to be added to objects
779 * in this bucket.
780 * @param {string|object} rule.action The action to be taken upon matching of
781 * all the conditions 'delete', 'setStorageClass', or 'AbortIncompleteMultipartUpload'.
782 * **Note**: For configuring a raw-formatted rule object to be passed as `action`
783 * please refer to the [examples]{@link https://cloud.google.com/storage/docs/managing-lifecycles#configexamples}.
784 * @param {object} rule.condition Condition a bucket must meet before the
785 * action occurson the bucket. Refer to followitn supported [conditions]{@link https://cloud.google.com/storage/docs/lifecycle#conditions}.
786 * @param {string} [rule.storageClass] When using the `setStorageClass`
787 * action, provide this option to dictate which storage class the object
788 * should update to.
789 * @param {AddLifecycleRuleOptions} [options] Configuration object.
790 * @param {boolean} [options.append=true] Append the new rule to the existing
791 * policy.
792 * @param {SetBucketMetadataCallback} [callback] Callback function.
793 * @returns {Promise<SetBucketMetadataResponse>}
794 *
795 * @example
796 * ```
797 * const {Storage} = require('@google-cloud/storage');
798 * const storage = new Storage();
799 * const bucket = storage.bucket('albums');
800 *
801 * //-
802 * // Automatically have an object deleted from this bucket once it is 3 years
803 * // of age.
804 * //-
805 * bucket.addLifecycleRule({
806 * action: 'delete',
807 * condition: {
808 * age: 365 * 3 // Specified in days.
809 * }
810 * }, function(err, apiResponse) {
811 * if (err) {
812 * // Error handling omitted.
813 * }
814 *
815 * const lifecycleRules = bucket.metadata.lifecycle.rule;
816 *
817 * // Iterate over the Object Lifecycle Management rules on this bucket.
818 * lifecycleRules.forEach(lifecycleRule => {});
819 * });
820 *
821 * //-
822 * // By default, the rule you provide will be added to the existing policy.
823 * // Optionally, you can disable this behavior to replace all of the
824 * // pre-existing rules.
825 * //-
826 * const options = {
827 * append: false
828 * };
829 *
830 * bucket.addLifecycleRule({
831 * action: 'delete',
832 * condition: {
833 * age: 365 * 3 // Specified in days.
834 * }
835 * }, options, function(err, apiResponse) {
836 * if (err) {
837 * // Error handling omitted.
838 * }
839 *
840 * // All rules have been replaced with the new "delete" rule.
841 *
842 * // Iterate over the Object Lifecycle Management rules on this bucket.
843 * lifecycleRules.forEach(lifecycleRule => {});
844 * });
845 *
846 * //-
847 * // For objects created before 2018, "downgrade" the storage class.
848 * //-
849 * bucket.addLifecycleRule({
850 * action: 'setStorageClass',
851 * storageClass: 'COLDLINE',
852 * condition: {
853 * createdBefore: new Date('2018')
854 * }
855 * }, function(err, apiResponse) {});
856 *
857 * //-
858 * // Delete objects created before 2016 which have the Coldline storage
859 * // class.
860 * //-
861 * bucket.addLifecycleRule({
862 * action: 'delete',
863 * condition: {
864 * matchesStorageClass: [
865 * 'COLDLINE'
866 * ],
867 * createdBefore: new Date('2016')
868 * }
869 * }, function(err, apiResponse) {});
870 *
871 * //-
872 * // Delete object that has a noncurrent timestamp that is at least 100 days.
873 * //-
874 * bucket.addLifecycleRule({
875 * action: 'delete',
876 * condition: {
877 * daysSinceNoncurrentTime: 100
878 * }
879 * }, function(err, apiResponse) {});
880 *
881 * //-
882 * // Delete object that has a noncurrent timestamp before 2020-01-01.
883 * //-
884 * bucket.addLifecycleRule({
885 * action: 'delete',
886 * condition: {
887 * noncurrentTimeBefore: new Date('2020-01-01')
888 * }
889 * }, function(err, apiResponse) {});
890 *
891 * //-
892 * // Delete object that has a customTime that is at least 100 days.
893 * //-
894 * bucket.addLifecycleRule({
895 * action: 'delete',
896 * condition: {
897 * daysSinceCustomTime: 100
898 * }
899 * }, function(err, apiResponse) ());
900 *
901 * //-
902 * // Delete object that has a customTime before 2020-01-01.
903 * //-
904 * bucket.addLifecycleRule({
905 * action: 'delete',
906 * condition: {
907 * customTimeBefore: new Date('2020-01-01')
908 * }
909 * }, function(err, apiResponse) {});
910 * ```
911 */
912 addLifecycleRule(rule, optionsOrCallback, callback) {
913 let options = {};
914 if (typeof optionsOrCallback === 'function') {
915 callback = optionsOrCallback;
916 }
917 else if (optionsOrCallback) {
918 options = optionsOrCallback;
919 }
920 options = options || {};
921 const rules = Array.isArray(rule) ? rule : [rule];
922 for (const curRule of rules) {
923 if (curRule.condition.createdBefore instanceof Date) {
924 curRule.condition.createdBefore = curRule.condition.createdBefore
925 .toISOString()
926 .replace(/T.+$/, '');
927 }
928 if (curRule.condition.customTimeBefore instanceof Date) {
929 curRule.condition.customTimeBefore = curRule.condition.customTimeBefore
930 .toISOString()
931 .replace(/T.+$/, '');
932 }
933 if (curRule.condition.noncurrentTimeBefore instanceof Date) {
934 curRule.condition.noncurrentTimeBefore =
935 curRule.condition.noncurrentTimeBefore
936 .toISOString()
937 .replace(/T.+$/, '');
938 }
939 }
940 if (options.append === false) {
941 this.setMetadata({ lifecycle: { rule: rules } }, options, callback);
942 return;
943 }
944 // The default behavior appends the previously-defined lifecycle rules with
945 // the new ones just passed in by the user.
946 this.getMetadata((err, metadata) => {
947 var _a, _b;
948 if (err) {
949 callback(err);
950 return;
951 }
952 const currentLifecycleRules = Array.isArray((_a = metadata.lifecycle) === null || _a === void 0 ? void 0 : _a.rule)
953 ? (_b = metadata.lifecycle) === null || _b === void 0 ? void 0 : _b.rule
954 : [];
955 this.setMetadata({
956 lifecycle: { rule: currentLifecycleRules.concat(rules) },
957 }, options, callback);
958 });
959 }
960 /**
961 * @typedef {object} CombineOptions
962 * @property {string} [kmsKeyName] Resource name of the Cloud KMS key, of
963 * the form
964 * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`,
965 * that will be used to encrypt the object. Overwrites the object
966 * metadata's `kms_key_name` value, if any.
967 * @property {string} [userProject] The ID of the project which will be
968 * billed for the request.
969 */
970 /**
971 * @callback CombineCallback
972 * @param {?Error} err Request error, if any.
973 * @param {File} newFile The new {@link File}.
974 * @param {object} apiResponse The full API response.
975 */
976 /**
977 * @typedef {array} CombineResponse
978 * @property {File} 0 The new {@link File}.
979 * @property {object} 1 The full API response.
980 */
981 /**
982 * Combine multiple files into one new file.
983 *
984 * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/compose| Objects: compose API Documentation}
985 *
986 * @throws {Error} if a non-array is provided as sources argument.
987 * @throws {Error} if no sources are provided.
988 * @throws {Error} if no destination is provided.
989 *
990 * @param {string[]|File[]} sources The source files that will be
991 * combined.
992 * @param {string|File} destination The file you would like the
993 * source files combined into.
994 * @param {CombineOptions} [options] Configuration options.
995 * @param {string} [options.kmsKeyName] Resource name of the Cloud KMS key, of
996 * the form
997 * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`,
998 * that will be used to encrypt the object. Overwrites the object
999 * metadata's `kms_key_name` value, if any.
1000 * @param {string} [options.userProject] The ID of the project which will be
1001 * billed for the request.
1002
1003 * @param {CombineCallback} [callback] Callback function.
1004 * @returns {Promise<CombineResponse>}
1005 *
1006 * @example
1007 * ```
1008 * const logBucket = storage.bucket('log-bucket');
1009 *
1010 * const sources = [
1011 * logBucket.file('2013-logs.txt'),
1012 * logBucket.file('2014-logs.txt')
1013 * ];
1014 *
1015 * const allLogs = logBucket.file('all-logs.txt');
1016 *
1017 * logBucket.combine(sources, allLogs, function(err, newFile, apiResponse) {
1018 * // newFile === allLogs
1019 * });
1020 *
1021 * //-
1022 * // If the callback is omitted, we'll return a Promise.
1023 * //-
1024 * logBucket.combine(sources, allLogs).then(function(data) {
1025 * const newFile = data[0];
1026 * const apiResponse = data[1];
1027 * });
1028 * ```
1029 */
1030 combine(sources, destination, optionsOrCallback, callback) {
1031 var _a;
1032 if (!Array.isArray(sources) || sources.length === 0) {
1033 throw new Error(BucketExceptionMessages.PROVIDE_SOURCE_FILE);
1034 }
1035 if (!destination) {
1036 throw new Error(BucketExceptionMessages.DESTINATION_FILE_NOT_SPECIFIED);
1037 }
1038 let options = {};
1039 if (typeof optionsOrCallback === 'function') {
1040 callback = optionsOrCallback;
1041 }
1042 else if (optionsOrCallback) {
1043 options = optionsOrCallback;
1044 }
1045 this.disableAutoRetryConditionallyIdempotent_(this.methods.setMetadata, // Not relevant but param is required
1046 AvailableServiceObjectMethods.setMetadata, // Same as above
1047 options);
1048 const convertToFile = (file) => {
1049 if (file instanceof File) {
1050 return file;
1051 }
1052 return this.file(file);
1053 };
1054 // eslint-disable-next-line @typescript-eslint/no-explicit-any
1055 sources = sources.map(convertToFile);
1056 const destinationFile = convertToFile(destination);
1057 callback = callback || util.noop;
1058 if (!destinationFile.metadata.contentType) {
1059 const destinationContentType = mime.getType(destinationFile.name) || undefined;
1060 if (destinationContentType) {
1061 destinationFile.metadata.contentType = destinationContentType;
1062 }
1063 }
1064 let maxRetries = this.storage.retryOptions.maxRetries;
1065 if ((((_a = destinationFile === null || destinationFile === void 0 ? void 0 : destinationFile.instancePreconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) ===
1066 undefined &&
1067 options.ifGenerationMatch === undefined &&
1068 this.storage.retryOptions.idempotencyStrategy ===
1069 IdempotencyStrategy.RetryConditional) ||
1070 this.storage.retryOptions.idempotencyStrategy ===
1071 IdempotencyStrategy.RetryNever) {
1072 maxRetries = 0;
1073 }
1074 if (options.ifGenerationMatch === undefined) {
1075 Object.assign(options, destinationFile.instancePreconditionOpts, options);
1076 }
1077 // Make the request from the destination File object.
1078 destinationFile.request({
1079 method: 'POST',
1080 uri: '/compose',
1081 maxRetries,
1082 json: {
1083 destination: {
1084 contentType: destinationFile.metadata.contentType,
1085 contentEncoding: destinationFile.metadata.contentEncoding,
1086 },
1087 sourceObjects: sources.map(source => {
1088 const sourceObject = {
1089 name: source.name,
1090 };
1091 if (source.metadata && source.metadata.generation) {
1092 sourceObject.generation = parseInt(source.metadata.generation.toString());
1093 }
1094 return sourceObject;
1095 }),
1096 },
1097 qs: options,
1098 }, (err, resp) => {
1099 this.storage.retryOptions.autoRetry = this.instanceRetryValue;
1100 if (err) {
1101 callback(err, null, resp);
1102 return;
1103 }
1104 callback(null, destinationFile, resp);
1105 });
1106 }
1107 /**
1108 * See a {@link https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll| Objects: watchAll request body}.
1109 *
1110 * @typedef {object} CreateChannelConfig
1111 * @property {string} address The address where notifications are
1112 * delivered for this channel.
1113 * @property {string} [delimiter] Returns results in a directory-like mode.
1114 * @property {number} [maxResults] Maximum number of `items` plus `prefixes`
1115 * to return in a single page of responses.
1116 * @property {string} [pageToken] A previously-returned page token
1117 * representing part of the larger set of results to view.
1118 * @property {string} [prefix] Filter results to objects whose names begin
1119 * with this prefix.
1120 * @property {string} [projection=noAcl] Set of properties to return.
1121 * @property {string} [userProject] The ID of the project which will be
1122 * billed for the request.
1123 * @property {boolean} [versions=false] If `true`, lists all versions of an object
1124 * as distinct results.
1125 */
1126 /**
1127 * @typedef {object} CreateChannelOptions
1128 * @property {string} [userProject] The ID of the project which will be
1129 * billed for the request.
1130 */
1131 /**
1132 * @typedef {array} CreateChannelResponse
1133 * @property {Channel} 0 The new {@link Channel}.
1134 * @property {object} 1 The full API response.
1135 */
1136 /**
1137 * @callback CreateChannelCallback
1138 * @param {?Error} err Request error, if any.
1139 * @param {Channel} channel The new {@link Channel}.
1140 * @param {object} apiResponse The full API response.
1141 */
1142 /**
1143 * Create a channel that will be notified when objects in this bucket changes.
1144 *
1145 * @throws {Error} If an ID is not provided.
1146 * @throws {Error} If an address is not provided.
1147 *
1148 * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll| Objects: watchAll API Documentation}
1149 *
1150 * @param {string} id The ID of the channel to create.
1151 * @param {CreateChannelConfig} config Configuration for creating channel.
1152 * @param {string} config.address The address where notifications are
1153 * delivered for this channel.
1154 * @param {string} [config.delimiter] Returns results in a directory-like mode.
1155 * @param {number} [config.maxResults] Maximum number of `items` plus `prefixes`
1156 * to return in a single page of responses.
1157 * @param {string} [config.pageToken] A previously-returned page token
1158 * representing part of the larger set of results to view.
1159 * @param {string} [config.prefix] Filter results to objects whose names begin
1160 * with this prefix.
1161 * @param {string} [config.projection=noAcl] Set of properties to return.
1162 * @param {string} [config.userProject] The ID of the project which will be
1163 * billed for the request.
1164 * @param {boolean} [config.versions=false] If `true`, lists all versions of an object
1165 * as distinct results.
1166 * @param {CreateChannelOptions} [options] Configuration options.
1167 * @param {string} [options.userProject] The ID of the project which will be
1168 * billed for the request.
1169 * @param {CreateChannelCallback} [callback] Callback function.
1170 * @returns {Promise<CreateChannelResponse>}
1171 *
1172 * @example
1173 * ```
1174 * const {Storage} = require('@google-cloud/storage');
1175 * const storage = new Storage();
1176 * const bucket = storage.bucket('albums');
1177 * const id = 'new-channel-id';
1178 *
1179 * const config = {
1180 * address: 'https://...'
1181 * };
1182 *
1183 * bucket.createChannel(id, config, function(err, channel, apiResponse) {
1184 * if (!err) {
1185 * // Channel created successfully.
1186 * }
1187 * });
1188 *
1189 * //-
1190 * // If the callback is omitted, we'll return a Promise.
1191 * //-
1192 * bucket.createChannel(id, config).then(function(data) {
1193 * const channel = data[0];
1194 * const apiResponse = data[1];
1195 * });
1196 * ```
1197 */
1198 createChannel(id, config, optionsOrCallback, callback) {
1199 if (typeof id !== 'string') {
1200 throw new Error(BucketExceptionMessages.CHANNEL_ID_REQUIRED);
1201 }
1202 let options = {};
1203 if (typeof optionsOrCallback === 'function') {
1204 callback = optionsOrCallback;
1205 }
1206 else if (optionsOrCallback) {
1207 options = optionsOrCallback;
1208 }
1209 this.request({
1210 method: 'POST',
1211 uri: '/o/watch',
1212 json: Object.assign({
1213 id,
1214 type: 'web_hook',
1215 }, config),
1216 qs: options,
1217 }, (err, apiResponse) => {
1218 if (err) {
1219 callback(err, null, apiResponse);
1220 return;
1221 }
1222 const resourceId = apiResponse.resourceId;
1223 const channel = this.storage.channel(id, resourceId);
1224 channel.metadata = apiResponse;
1225 callback(null, channel, apiResponse);
1226 });
1227 }
1228 /**
1229 * Metadata to set for the Notification.
1230 *
1231 * @typedef {object} CreateNotificationOptions
1232 * @property {object} [customAttributes] An optional list of additional
1233 * attributes to attach to each Cloud PubSub message published for this
1234 * notification subscription.
1235 * @property {string[]} [eventTypes] If present, only send notifications about
1236 * listed event types. If empty, sent notifications for all event types.
1237 * @property {string} [objectNamePrefix] If present, only apply this
1238 * notification configuration to object names that begin with this prefix.
1239 * @property {string} [payloadFormat] The desired content of the Payload.
1240 * Defaults to `JSON_API_V1`.
1241 *
1242 * Acceptable values are:
1243 * - `JSON_API_V1`
1244 *
1245 * - `NONE`
1246 * @property {string} [userProject] The ID of the project which will be
1247 * billed for the request.
1248 */
1249 /**
1250 * @callback CreateNotificationCallback
1251 * @param {?Error} err Request error, if any.
1252 * @param {Notification} notification The new {@link Notification}.
1253 * @param {object} apiResponse The full API response.
1254 */
1255 /**
1256 * @typedef {array} CreateNotificationResponse
1257 * @property {Notification} 0 The new {@link Notification}.
1258 * @property {object} 1 The full API response.
1259 */
1260 /**
1261 * Creates a notification subscription for the bucket.
1262 *
1263 * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/insert| Notifications: insert}
1264 *
1265 * @param {Topic|string} topic The Cloud PubSub topic to which this
1266 * subscription publishes. If the project ID is omitted, the current
1267 * project ID will be used.
1268 *
1269 * Acceptable formats are:
1270 * - `projects/grape-spaceship-123/topics/my-topic`
1271 *
1272 * - `my-topic`
1273 * @param {CreateNotificationOptions} [options] Metadata to set for the
1274 * notification.
1275 * @param {object} [options.customAttributes] An optional list of additional
1276 * attributes to attach to each Cloud PubSub message published for this
1277 * notification subscription.
1278 * @param {string[]} [options.eventTypes] If present, only send notifications about
1279 * listed event types. If empty, sent notifications for all event types.
1280 * @param {string} [options.objectNamePrefix] If present, only apply this
1281 * notification configuration to object names that begin with this prefix.
1282 * @param {string} [options.payloadFormat] The desired content of the Payload.
1283 * Defaults to `JSON_API_V1`.
1284 *
1285 * Acceptable values are:
1286 * - `JSON_API_V1`
1287 *
1288 * - `NONE`
1289 * @param {string} [options.userProject] The ID of the project which will be
1290 * billed for the request.
1291 * @param {CreateNotificationCallback} [callback] Callback function.
1292 * @returns {Promise<CreateNotificationResponse>}
1293 * @throws {Error} If a valid topic is not provided.
1294 * @see Notification#create
1295 *
1296 * @example
1297 * ```
1298 * const {Storage} = require('@google-cloud/storage');
1299 * const storage = new Storage();
1300 * const myBucket = storage.bucket('my-bucket');
1301 *
1302 * const callback = function(err, notification, apiResponse) {
1303 * if (!err) {
1304 * // The notification was created successfully.
1305 * }
1306 * };
1307 *
1308 * myBucket.createNotification('my-topic', callback);
1309 *
1310 * //-
1311 * // Configure the nofiication by providing Notification metadata.
1312 * //-
1313 * const metadata = {
1314 * objectNamePrefix: 'prefix-'
1315 * };
1316 *
1317 * myBucket.createNotification('my-topic', metadata, callback);
1318 *
1319 * //-
1320 * // If the callback is omitted, we'll return a Promise.
1321 * //-
1322 * myBucket.createNotification('my-topic').then(function(data) {
1323 * const notification = data[0];
1324 * const apiResponse = data[1];
1325 * });
1326 *
1327 * ```
1328 * @example <caption>include:samples/createNotification.js</caption>
1329 * region_tag:storage_create_bucket_notifications
1330 * Another example:
1331 */
1332 createNotification(topic, optionsOrCallback, callback) {
1333 let options = {};
1334 if (typeof optionsOrCallback === 'function') {
1335 callback = optionsOrCallback;
1336 }
1337 else if (optionsOrCallback) {
1338 options = optionsOrCallback;
1339 }
1340 const topicIsObject = topic !== null && typeof topic === 'object';
1341 if (topicIsObject && util.isCustomType(topic, 'pubsub/topic')) {
1342 // eslint-disable-next-line @typescript-eslint/no-explicit-any
1343 topic = topic.name;
1344 }
1345 if (typeof topic !== 'string') {
1346 throw new Error(BucketExceptionMessages.TOPIC_NAME_REQUIRED);
1347 }
1348 const body = Object.assign({ topic }, options);
1349 if (body.topic.indexOf('projects') !== 0) {
1350 body.topic = 'projects/{{projectId}}/topics/' + body.topic;
1351 }
1352 body.topic = `//pubsub.${this.storage.universeDomain}/` + body.topic;
1353 if (!body.payloadFormat) {
1354 body.payloadFormat = 'JSON_API_V1';
1355 }
1356 const query = {};
1357 if (body.userProject) {
1358 query.userProject = body.userProject;
1359 delete body.userProject;
1360 }
1361 this.request({
1362 method: 'POST',
1363 uri: '/notificationConfigs',
1364 json: convertObjKeysToSnakeCase(body),
1365 qs: query,
1366 maxRetries: 0, //explicitly set this value since this is a non-idempotent function
1367 }, (err, apiResponse) => {
1368 if (err) {
1369 callback(err, null, apiResponse);
1370 return;
1371 }
1372 const notification = this.notification(apiResponse.id);
1373 notification.metadata = apiResponse;
1374 callback(null, notification, apiResponse);
1375 });
1376 }
1377 /**
1378 * @typedef {object} DeleteFilesOptions Query object. See {@link Bucket#getFiles}
1379 * for all of the supported properties.
1380 * @property {boolean} [force] Suppress errors until all files have been
1381 * processed.
1382 */
1383 /**
1384 * @callback DeleteFilesCallback
1385 * @param {?Error|?Error[]} err Request error, if any, or array of errors from
1386 * files that were not able to be deleted.
1387 * @param {object} [apiResponse] The full API response.
1388 */
1389 /**
1390 * Iterate over the bucket's files, calling `file.delete()` on each.
1391 *
1392 * <strong>This is not an atomic request.</strong> A delete attempt will be
1393 * made for each file individually. Any one can fail, in which case only a
1394 * portion of the files you intended to be deleted would have.
1395 *
1396 * Operations are performed in parallel, up to 10 at once. The first error
1397 * breaks the loop and will execute the provided callback with it. Specify
1398 * `{ force: true }` to suppress the errors until all files have had a chance
1399 * to be processed.
1400 *
1401 * File preconditions cannot be passed to this function. It will not retry unless
1402 * the idempotency strategy is set to retry always.
1403 *
1404 * The `query` object passed as the first argument will also be passed to
1405 * {@link Bucket#getFiles}.
1406 *
1407 * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/delete| Objects: delete API Documentation}
1408 *
1409 * @param {DeleteFilesOptions} [query] Query object. See {@link Bucket#getFiles}
1410 * @param {boolean} [query.force] Suppress errors until all files have been
1411 * processed.
1412 * @param {DeleteFilesCallback} [callback] Callback function.
1413 * @returns {Promise}
1414 *
1415 * @example
1416 * ```
1417 * const {Storage} = require('@google-cloud/storage');
1418 * const storage = new Storage();
1419 * const bucket = storage.bucket('albums');
1420 *
1421 * //-
1422 * // Delete all of the files in the bucket.
1423 * //-
1424 * bucket.deleteFiles(function(err) {});
1425 *
1426 * //-
1427 * // By default, if a file cannot be deleted, this method will stop deleting
1428 * // files from your bucket. You can override this setting with `force:
1429 * // true`.
1430 * //-
1431 * bucket.deleteFiles({
1432 * force: true
1433 * }, function(errors) {
1434 * // `errors`:
1435 * // Array of errors if any occurred, otherwise null.
1436 * });
1437 *
1438 * //-
1439 * // The first argument to this method acts as a query to
1440 * // {@link Bucket#getFiles}. As an example, you can delete files
1441 * // which match a prefix.
1442 * //-
1443 * bucket.deleteFiles({
1444 * prefix: 'images/'
1445 * }, function(err) {
1446 * if (!err) {
1447 * // All files in the `images` directory have been deleted.
1448 * }
1449 * });
1450 *
1451 * //-
1452 * // If the callback is omitted, we'll return a Promise.
1453 * //-
1454 * bucket.deleteFiles().then(function() {});
1455 * ```
1456 */
1457 deleteFiles(queryOrCallback, callback) {
1458 let query = {};
1459 if (typeof queryOrCallback === 'function') {
1460 callback = queryOrCallback;
1461 }
1462 else if (queryOrCallback) {
1463 query = queryOrCallback;
1464 }
1465 const MAX_PARALLEL_LIMIT = 10;
1466 const MAX_QUEUE_SIZE = 1000;
1467 const errors = [];
1468 const deleteFile = (file) => {
1469 return file.delete(query).catch(err => {
1470 if (!query.force) {
1471 throw err;
1472 }
1473 errors.push(err);
1474 });
1475 };
1476 (async () => {
1477 try {
1478 let promises = [];
1479 const limit = pLimit(MAX_PARALLEL_LIMIT);
1480 const filesStream = this.getFilesStream(query);
1481 for await (const curFile of filesStream) {
1482 if (promises.length >= MAX_QUEUE_SIZE) {
1483 await Promise.all(promises);
1484 promises = [];
1485 }
1486 promises.push(limit(() => deleteFile(curFile)).catch(e => {
1487 filesStream.destroy();
1488 throw e;
1489 }));
1490 }
1491 await Promise.all(promises);
1492 callback(errors.length > 0 ? errors : null);
1493 }
1494 catch (e) {
1495 callback(e);
1496 return;
1497 }
1498 })();
1499 }
1500 /**
1501 * @deprecated
1502 * @typedef {array} DeleteLabelsResponse
1503 * @property {object} 0 The full API response.
1504 */
1505 /**
1506 * @deprecated
1507 * @callback DeleteLabelsCallback
1508 * @param {?Error} err Request error, if any.
1509 * @param {object} metadata Bucket's metadata.
1510 */
1511 /**
1512 * @deprecated Use setMetadata directly
1513 * Delete one or more labels from this bucket.
1514 *
1515 * @param {string|string[]} [labels] The labels to delete. If no labels are
1516 * provided, all of the labels are removed.
1517 * @param {DeleteLabelsCallback} [callback] Callback function.
1518 * @param {DeleteLabelsOptions} [options] Options, including precondition options
1519 * @returns {Promise<DeleteLabelsResponse>}
1520 *
1521 * @example
1522 * ```
1523 * const {Storage} = require('@google-cloud/storage');
1524 * const storage = new Storage();
1525 * const bucket = storage.bucket('albums');
1526 *
1527 * //-
1528 * // Delete all of the labels from this bucket.
1529 * //-
1530 * bucket.deleteLabels(function(err, apiResponse) {});
1531 *
1532 * //-
1533 * // Delete a single label.
1534 * //-
1535 * bucket.deleteLabels('labelone', function(err, apiResponse) {});
1536 *
1537 * //-
1538 * // Delete a specific set of labels.
1539 * //-
1540 * bucket.deleteLabels([
1541 * 'labelone',
1542 * 'labeltwo'
1543 * ], function(err, apiResponse) {});
1544 *
1545 * //-
1546 * // If the callback is omitted, we'll return a Promise.
1547 * //-
1548 * bucket.deleteLabels().then(function(data) {
1549 * const apiResponse = data[0];
1550 * });
1551 * ```
1552 */
1553 deleteLabels(labelsOrCallbackOrOptions, optionsOrCallback, callback) {
1554 let labels = new Array();
1555 let options = {};
1556 if (typeof labelsOrCallbackOrOptions === 'function') {
1557 callback = labelsOrCallbackOrOptions;
1558 }
1559 else if (typeof labelsOrCallbackOrOptions === 'string') {
1560 labels = [labelsOrCallbackOrOptions];
1561 }
1562 else if (Array.isArray(labelsOrCallbackOrOptions)) {
1563 labels = labelsOrCallbackOrOptions;
1564 }
1565 else if (labelsOrCallbackOrOptions) {
1566 options = labelsOrCallbackOrOptions;
1567 }
1568 if (typeof optionsOrCallback === 'function') {
1569 callback = optionsOrCallback;
1570 }
1571 else if (optionsOrCallback) {
1572 options = optionsOrCallback;
1573 }
1574 const deleteLabels = (labels) => {
1575 const nullLabelMap = labels.reduce((nullLabelMap, labelKey) => {
1576 nullLabelMap[labelKey] = null;
1577 return nullLabelMap;
1578 }, {});
1579 if ((options === null || options === void 0 ? void 0 : options.ifMetagenerationMatch) !== undefined) {
1580 this.setLabels(nullLabelMap, options, callback);
1581 }
1582 else {
1583 this.setLabels(nullLabelMap, callback);
1584 }
1585 };
1586 if (labels.length === 0) {
1587 this.getLabels((err, labels) => {
1588 if (err) {
1589 callback(err);
1590 return;
1591 }
1592 deleteLabels(Object.keys(labels));
1593 });
1594 }
1595 else {
1596 deleteLabels(labels);
1597 }
1598 }
1599 /**
1600 * @typedef {array} DisableRequesterPaysResponse
1601 * @property {object} 0 The full API response.
1602 */
1603 /**
1604 * @callback DisableRequesterPaysCallback
1605 * @param {?Error} err Request error, if any.
1606 * @param {object} apiResponse The full API response.
1607 */
1608 /**
1609 * <div class="notice">
1610 * <strong>Early Access Testers Only</strong>
1611 * <p>
1612 * This feature is not yet widely-available.
1613 * </p>
1614 * </div>
1615 *
1616 * Disable `requesterPays` functionality from this bucket.
1617 *
1618 * @param {DisableRequesterPaysCallback} [callback] Callback function.
1619 * @param {DisableRequesterPaysOptions} [options] Options, including precondition options
1620 * @returns {Promise<DisableRequesterPaysCallback>}
1621 *
1622 * @example
1623 * ```
1624 * const {Storage} = require('@google-cloud/storage');
1625 * const storage = new Storage();
1626 * const bucket = storage.bucket('albums');
1627 *
1628 * bucket.disableRequesterPays(function(err, apiResponse) {
1629 * if (!err) {
1630 * // requesterPays functionality disabled successfully.
1631 * }
1632 * });
1633 *
1634 * //-
1635 * // If the callback is omitted, we'll return a Promise.
1636 * //-
1637 * bucket.disableRequesterPays().then(function(data) {
1638 * const apiResponse = data[0];
1639 * });
1640 *
1641 * ```
1642 * @example <caption>include:samples/requesterPays.js</caption>
1643 * region_tag:storage_disable_requester_pays
1644 * Example of disabling requester pays:
1645 */
1646 disableRequesterPays(optionsOrCallback, callback) {
1647 let options = {};
1648 if (typeof optionsOrCallback === 'function') {
1649 callback = optionsOrCallback;
1650 }
1651 else if (optionsOrCallback) {
1652 options = optionsOrCallback;
1653 }
1654 this.setMetadata({
1655 billing: {
1656 requesterPays: false,
1657 },
1658 }, options, callback);
1659 }
1660 /**
1661 * Configuration object for enabling logging.
1662 *
1663 * @typedef {object} EnableLoggingOptions
1664 * @property {string|Bucket} [bucket] The bucket for the log entries. By
1665 * default, the current bucket is used.
1666 * @property {string} prefix A unique prefix for log object names.
1667 */
1668 /**
1669 * Enable logging functionality for this bucket. This will make two API
1670 * requests, first to grant Cloud Storage WRITE permission to the bucket, then
1671 * to set the appropriate configuration on the Bucket's metadata.
1672 *
1673 * @param {EnableLoggingOptions} config Configuration options.
1674 * @param {string|Bucket} [config.bucket] The bucket for the log entries. By
1675 * default, the current bucket is used.
1676 * @param {string} config.prefix A unique prefix for log object names.
1677 * @param {SetBucketMetadataCallback} [callback] Callback function.
1678 * @returns {Promise<SetBucketMetadataResponse>}
1679 *
1680 * @example
1681 * ```
1682 * const {Storage} = require('@google-cloud/storage');
1683 * const storage = new Storage();
1684 * const bucket = storage.bucket('albums');
1685 *
1686 * const config = {
1687 * prefix: 'log'
1688 * };
1689 *
1690 * bucket.enableLogging(config, function(err, apiResponse) {
1691 * if (!err) {
1692 * // Logging functionality enabled successfully.
1693 * }
1694 * });
1695 *
1696 * ```
1697 * @example
1698 * Optionally, provide a destination bucket.
1699 * ```
1700 * const config = {
1701 * prefix: 'log',
1702 * bucket: 'destination-bucket'
1703 * };
1704 *
1705 * bucket.enableLogging(config, function(err, apiResponse) {});
1706 * ```
1707 *
1708 * @example
1709 * If the callback is omitted, we'll return a Promise.
1710 * ```
1711 * bucket.enableLogging(config).then(function(data) {
1712 * const apiResponse = data[0];
1713 * });
1714 * ```
1715 */
1716 enableLogging(config, callback) {
1717 if (!config ||
1718 typeof config === 'function' ||
1719 typeof config.prefix === 'undefined') {
1720 throw new Error(BucketExceptionMessages.CONFIGURATION_OBJECT_PREFIX_REQUIRED);
1721 }
1722 let logBucket = this.id;
1723 if (config.bucket && config.bucket instanceof Bucket) {
1724 logBucket = config.bucket.id;
1725 }
1726 else if (config.bucket && typeof config.bucket === 'string') {
1727 logBucket = config.bucket;
1728 }
1729 const options = {};
1730 if (config === null || config === void 0 ? void 0 : config.ifMetagenerationMatch) {
1731 options.ifMetagenerationMatch = config.ifMetagenerationMatch;
1732 }
1733 if (config === null || config === void 0 ? void 0 : config.ifMetagenerationNotMatch) {
1734 options.ifMetagenerationNotMatch = config.ifMetagenerationNotMatch;
1735 }
1736 (async () => {
1737 try {
1738 const [policy] = await this.iam.getPolicy();
1739 policy.bindings.push({
1740 members: ['group:cloud-storage-analytics@google.com'],
1741 role: 'roles/storage.objectCreator',
1742 });
1743 await this.iam.setPolicy(policy);
1744 this.setMetadata({
1745 logging: {
1746 logBucket,
1747 logObjectPrefix: config.prefix,
1748 },
1749 }, options, callback);
1750 }
1751 catch (e) {
1752 callback(e);
1753 return;
1754 }
1755 })();
1756 }
1757 /**
1758 * @typedef {array} EnableRequesterPaysResponse
1759 * @property {object} 0 The full API response.
1760 */
1761 /**
1762 * @callback EnableRequesterPaysCallback
1763 * @param {?Error} err Request error, if any.
1764 * @param {object} apiResponse The full API response.
1765 */
1766 /**
1767 * <div class="notice">
1768 * <strong>Early Access Testers Only</strong>
1769 * <p>
1770 * This feature is not yet widely-available.
1771 * </p>
1772 * </div>
1773 *
1774 * Enable `requesterPays` functionality for this bucket. This enables you, the
1775 * bucket owner, to have the requesting user assume the charges for the access
1776 * to your bucket and its contents.
1777 *
1778 * @param {EnableRequesterPaysCallback | EnableRequesterPaysOptions} [optionsOrCallback]
1779 * Callback function or precondition options.
1780 * @returns {Promise<EnableRequesterPaysResponse>}
1781 *
1782 * @example
1783 * ```
1784 * const {Storage} = require('@google-cloud/storage');
1785 * const storage = new Storage();
1786 * const bucket = storage.bucket('albums');
1787 *
1788 * bucket.enableRequesterPays(function(err, apiResponse) {
1789 * if (!err) {
1790 * // requesterPays functionality enabled successfully.
1791 * }
1792 * });
1793 *
1794 * //-
1795 * // If the callback is omitted, we'll return a Promise.
1796 * //-
1797 * bucket.enableRequesterPays().then(function(data) {
1798 * const apiResponse = data[0];
1799 * });
1800 *
1801 * ```
1802 * @example <caption>include:samples/requesterPays.js</caption>
1803 * region_tag:storage_enable_requester_pays
1804 * Example of enabling requester pays:
1805 */
1806 enableRequesterPays(optionsOrCallback, cb) {
1807 let options = {};
1808 if (typeof optionsOrCallback === 'function') {
1809 cb = optionsOrCallback;
1810 }
1811 else if (optionsOrCallback) {
1812 options = optionsOrCallback;
1813 }
1814 this.setMetadata({
1815 billing: {
1816 requesterPays: true,
1817 },
1818 }, options, cb);
1819 }
1820 /**
1821 * Create a {@link File} object. See {@link File} to see how to handle
1822 * the different use cases you may have.
1823 *
1824 * @param {string} name The name of the file in this bucket.
1825 * @param {FileOptions} [options] Configuration options.
1826 * @param {string|number} [options.generation] Only use a specific revision of
1827 * this file.
1828 * @param {string} [options.encryptionKey] A custom encryption key. See
1829 * {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys}.
1830 * @param {string} [options.kmsKeyName] The name of the Cloud KMS key that will
1831 * be used to encrypt the object. Must be in the format:
1832 * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`.
1833 * KMS key ring must use the same location as the bucket.
1834 * @param {string} [options.userProject] The ID of the project which will be
1835 * billed for all requests made from File object.
1836 * @returns {File}
1837 *
1838 * @example
1839 * ```
1840 * const {Storage} = require('@google-cloud/storage');
1841 * const storage = new Storage();
1842 * const bucket = storage.bucket('albums');
1843 * const file = bucket.file('my-existing-file.png');
1844 * ```
1845 */
1846 file(name, options) {
1847 if (!name) {
1848 throw Error(BucketExceptionMessages.SPECIFY_FILE_NAME);
1849 }
1850 return new File(this, name, options);
1851 }
1852 /**
1853 * @typedef {array} GetFilesResponse
1854 * @property {File[]} 0 Array of {@link File} instances.
1855 * @param {object} nextQuery 1 A query object to receive more results.
1856 * @param {object} apiResponse 2 The full API response.
1857 */
1858 /**
1859 * @callback GetFilesCallback
1860 * @param {?Error} err Request error, if any.
1861 * @param {File[]} files Array of {@link File} instances.
1862 * @param {object} nextQuery A query object to receive more results.
1863 * @param {object} apiResponse The full API response.
1864 */
1865 /**
1866 * Query object for listing files.
1867 *
1868 * @typedef {object} GetFilesOptions
1869 * @property {boolean} [autoPaginate=true] Have pagination handled
1870 * automatically.
1871 * @property {string} [delimiter] Results will contain only objects whose
1872 * names, aside from the prefix, do not contain delimiter. Objects whose
1873 * names, aside from the prefix, contain delimiter will have their name
1874 * truncated after the delimiter, returned in `apiResponse.prefixes`.
1875 * Duplicate prefixes are omitted.
1876 * @property {string} [endOffset] Filter results to objects whose names are
1877 * lexicographically before endOffset. If startOffset is also set, the objects
1878 * listed have names between startOffset (inclusive) and endOffset (exclusive).
1879 * @property {boolean} [includeFoldersAsPrefixes] If true, includes folders and
1880 * managed folders in the set of prefixes returned by the query. Only applicable if
1881 * delimiter is set to / and autoPaginate is set to false.
1882 * See: https://cloud.google.com/storage/docs/managed-folders
1883 * @property {boolean} [includeTrailingDelimiter] If true, objects that end in
1884 * exactly one instance of delimiter have their metadata included in items[]
1885 * in addition to the relevant part of the object name appearing in prefixes[].
1886 * @property {string} [prefix] Filter results to objects whose names begin
1887 * with this prefix.
1888 * @property {string} [matchGlob] A glob pattern used to filter results,
1889 * for example foo*bar
1890 * @property {number} [maxApiCalls] Maximum number of API calls to make.
1891 * @property {number} [maxResults] Maximum number of items plus prefixes to
1892 * return per call.
1893 * Note: By default will handle pagination automatically
1894 * if more than 1 page worth of results are requested per call.
1895 * When `autoPaginate` is set to `false` the smaller of `maxResults`
1896 * or 1 page of results will be returned per call.
1897 * @property {string} [pageToken] A previously-returned page token
1898 * representing part of the larger set of results to view.
1899 * @property {boolean} [softDeleted] If true, only soft-deleted object versions will be
1900 * listed as distinct results in order of generation number. Note `soft_deleted` and
1901 * `versions` cannot be set to true simultaneously.
1902 * @property {string} [startOffset] Filter results to objects whose names are
1903 * lexicographically equal to or after startOffset. If endOffset is also set,
1904 * the objects listed have names between startOffset (inclusive) and endOffset (exclusive).
1905 * @property {string} [userProject] The ID of the project which will be
1906 * billed for the request.
1907 * @property {boolean} [versions] If true, returns File objects scoped to
1908 * their versions.
1909 */
1910 /**
1911 * Get {@link File} objects for the files currently in the bucket.
1912 *
1913 * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/list| Objects: list API Documentation}
1914 *
1915 * @param {GetFilesOptions} [query] Query object for listing files.
1916 * @param {boolean} [query.autoPaginate=true] Have pagination handled
1917 * automatically.
1918 * @param {string} [query.delimiter] Results will contain only objects whose
1919 * names, aside from the prefix, do not contain delimiter. Objects whose
1920 * names, aside from the prefix, contain delimiter will have their name
1921 * truncated after the delimiter, returned in `apiResponse.prefixes`.
1922 * Duplicate prefixes are omitted.
1923 * @param {string} [query.endOffset] Filter results to objects whose names are
1924 * lexicographically before endOffset. If startOffset is also set, the objects
1925 * listed have names between startOffset (inclusive) and endOffset (exclusive).
1926 * @param {boolean} [query.includeFoldersAsPrefixes] If true, includes folders and
1927 * managed folders in the set of prefixes returned by the query. Only applicable if
1928 * delimiter is set to / and autoPaginate is set to false.
1929 * See: https://cloud.google.com/storage/docs/managed-folders
1930 * @param {boolean} [query.includeTrailingDelimiter] If true, objects that end in
1931 * exactly one instance of delimiter have their metadata included in items[]
1932 * in addition to the relevant part of the object name appearing in prefixes[].
1933 * @param {string} [query.prefix] Filter results to objects whose names begin
1934 * with this prefix.
1935 * @param {number} [query.maxApiCalls] Maximum number of API calls to make.
1936 * @param {number} [query.maxResults] Maximum number of items plus prefixes to
1937 * return per call.
1938 * Note: By default will handle pagination automatically
1939 * if more than 1 page worth of results are requested per call.
1940 * When `autoPaginate` is set to `false` the smaller of `maxResults`
1941 * or 1 page of results will be returned per call.
1942 * @param {string} [query.pageToken] A previously-returned page token
1943 * representing part of the larger set of results to view.
1944 * @param {boolean} [query.softDeleted] If true, only soft-deleted object versions will be
1945 * listed as distinct results in order of generation number. Note `soft_deleted` and
1946 * `versions` cannot be set to true simultaneously.
1947 * @param {string} [query.startOffset] Filter results to objects whose names are
1948 * lexicographically equal to or after startOffset. If endOffset is also set,
1949 * the objects listed have names between startOffset (inclusive) and endOffset (exclusive).
1950 * @param {string} [query.userProject] The ID of the project which will be
1951 * billed for the request.
1952 * @param {boolean} [query.versions] If true, returns File objects scoped to
1953 * their versions.
1954 * @param {GetFilesCallback} [callback] Callback function.
1955 * @returns {Promise<GetFilesResponse>}
1956 *
1957 * @example
1958 * ```
1959 * const {Storage} = require('@google-cloud/storage');
1960 * const storage = new Storage();
1961 * const bucket = storage.bucket('albums');
1962 *
1963 * bucket.getFiles(function(err, files) {
1964 * if (!err) {
1965 * // files is an array of File objects.
1966 * }
1967 * });
1968 *
1969 * //-
1970 * // If your bucket has versioning enabled, you can get all of your files
1971 * // scoped to their generation.
1972 * //-
1973 * bucket.getFiles({
1974 * versions: true
1975 * }, function(err, files) {
1976 * // Each file is scoped to its generation.
1977 * });
1978 *
1979 * //-
1980 * // To control how many API requests are made and page through the results
1981 * // manually, set `autoPaginate` to `false`.
1982 * //-
1983 * const callback = function(err, files, nextQuery, apiResponse) {
1984 * if (nextQuery) {
1985 * // More results exist.
1986 * bucket.getFiles(nextQuery, callback);
1987 * }
1988 *
1989 * // The `metadata` property is populated for you with the metadata at the
1990 * // time of fetching.
1991 * files[0].metadata;
1992 *
1993 * // However, in cases where you are concerned the metadata could have
1994 * // changed, use the `getMetadata` method.
1995 * files[0].getMetadata(function(err, metadata) {});
1996 * };
1997 *
1998 * bucket.getFiles({
1999 * autoPaginate: false
2000 * }, callback);
2001 *
2002 * //-
2003 * // If the callback is omitted, we'll return a Promise.
2004 * //-
2005 * bucket.getFiles().then(function(data) {
2006 * const files = data[0];
2007 * });
2008 *
2009 * ```
2010 * @example
2011 * <h6>Simulating a File System</h6><p>With `autoPaginate: false`, it's possible to iterate over files which incorporate a common structure using a delimiter.</p><p>Consider the following remote objects:</p><ol><li>"a"</li><li>"a/b/c/d"</li><li>"b/d/e"</li></ol><p>Using a delimiter of `/` will return a single file, "a".</p><p>`apiResponse.prefixes` will return the "sub-directories" that were found:</p><ol><li>"a/"</li><li>"b/"</li></ol>
2012 * ```
2013 * bucket.getFiles({
2014 * autoPaginate: false,
2015 * delimiter: '/'
2016 * }, function(err, files, nextQuery, apiResponse) {
2017 * // files = [
2018 * // {File} // File object for file "a"
2019 * // ]
2020 *
2021 * // apiResponse.prefixes = [
2022 * // 'a/',
2023 * // 'b/'
2024 * // ]
2025 * });
2026 * ```
2027 *
2028 * @example
2029 * Using prefixes, it's now possible to simulate a file system with follow-up requests.
2030 * ```
2031 * bucket.getFiles({
2032 * autoPaginate: false,
2033 * delimiter: '/',
2034 * prefix: 'a/'
2035 * }, function(err, files, nextQuery, apiResponse) {
2036 * // No files found within "directory" a.
2037 * // files = []
2038 *
2039 * // However, a "sub-directory" was found.
2040 * // This prefix can be used to continue traversing the "file system".
2041 * // apiResponse.prefixes = [
2042 * // 'a/b/'
2043 * // ]
2044 * });
2045 * ```
2046 *
2047 * @example <caption>include:samples/files.js</caption>
2048 * region_tag:storage_list_files
2049 * Another example:
2050 *
2051 * @example <caption>include:samples/files.js</caption>
2052 * region_tag:storage_list_files_with_prefix
2053 * Example of listing files, filtered by a prefix:
2054 */
2055 getFiles(queryOrCallback, callback) {
2056 let query = typeof queryOrCallback === 'object' ? queryOrCallback : {};
2057 if (!callback) {
2058 callback = queryOrCallback;
2059 }
2060 query = Object.assign({}, query);
2061 this.request({
2062 uri: '/o',
2063 qs: query,
2064 }, (err, resp) => {
2065 if (err) {
2066 // eslint-disable-next-line @typescript-eslint/no-explicit-any
2067 callback(err, null, null, resp);
2068 return;
2069 }
2070 const itemsArray = resp.items ? resp.items : [];
2071 const files = itemsArray.map((file) => {
2072 const options = {};
2073 if (query.fields) {
2074 const fileInstance = file;
2075 return fileInstance;
2076 }
2077 if (query.versions) {
2078 options.generation = file.generation;
2079 }
2080 if (file.kmsKeyName) {
2081 options.kmsKeyName = file.kmsKeyName;
2082 }
2083 const fileInstance = this.file(file.name, options);
2084 fileInstance.metadata = file;
2085 return fileInstance;
2086 });
2087 let nextQuery = null;
2088 if (resp.nextPageToken) {
2089 nextQuery = Object.assign({}, query, {
2090 pageToken: resp.nextPageToken,
2091 });
2092 }
2093 // eslint-disable-next-line @typescript-eslint/no-explicit-any
2094 callback(null, files, nextQuery, resp);
2095 });
2096 }
2097 /**
2098 * @deprecated
2099 * @typedef {object} GetLabelsOptions Configuration options for Bucket#getLabels().
2100 * @param {string} [userProject] The ID of the project which will be
2101 * billed for the request.
2102 */
2103 /**
2104 * @deprecated
2105 * @typedef {array} GetLabelsResponse
2106 * @property {object} 0 Object of labels currently set on this bucket.
2107 */
2108 /**
2109 * @deprecated
2110 * @callback GetLabelsCallback
2111 * @param {?Error} err Request error, if any.
2112 * @param {object} labels Object of labels currently set on this bucket.
2113 */
2114 /**
2115 * @deprecated Use getMetadata directly.
2116 * Get the labels currently set on this bucket.
2117 *
2118 * @param {object} [options] Configuration options.
2119 * @param {string} [options.userProject] The ID of the project which will be
2120 * billed for the request.
2121 * @param {GetLabelsCallback} [callback] Callback function.
2122 * @returns {Promise<GetLabelsCallback>}
2123 *
2124 * @example
2125 * ```
2126 * const {Storage} = require('@google-cloud/storage');
2127 * const storage = new Storage();
2128 * const bucket = storage.bucket('albums');
2129 *
2130 * bucket.getLabels(function(err, labels) {
2131 * if (err) {
2132 * // Error handling omitted.
2133 * }
2134 *
2135 * // labels = {
2136 * // label: 'labelValue',
2137 * // ...
2138 * // }
2139 * });
2140 *
2141 * //-
2142 * // If the callback is omitted, we'll return a Promise.
2143 * //-
2144 * bucket.getLabels().then(function(data) {
2145 * const labels = data[0];
2146 * });
2147 * ```
2148 */
2149 getLabels(optionsOrCallback, callback) {
2150 let options = {};
2151 if (typeof optionsOrCallback === 'function') {
2152 callback = optionsOrCallback;
2153 }
2154 else if (optionsOrCallback) {
2155 options = optionsOrCallback;
2156 }
2157 this.getMetadata(options, (err, metadata) => {
2158 if (err) {
2159 callback(err, null);
2160 return;
2161 }
2162 callback(null, (metadata === null || metadata === void 0 ? void 0 : metadata.labels) || {});
2163 });
2164 }
2165 /**
2166 * @typedef {object} GetNotificationsOptions Configuration options for Bucket#getNotification().
2167 * @property {string} [userProject] The ID of the project which will be
2168 * billed for the request.
2169 */
2170 /**
2171 * @callback GetNotificationsCallback
2172 * @param {?Error} err Request error, if any.
2173 * @param {Notification[]} notifications Array of {@link Notification}
2174 * instances.
2175 * @param {object} apiResponse The full API response.
2176 */
2177 /**
2178 * @typedef {array} GetNotificationsResponse
2179 * @property {Notification[]} 0 Array of {@link Notification} instances.
2180 * @property {object} 1 The full API response.
2181 */
2182 /**
2183 * Retrieves a list of notification subscriptions for a given bucket.
2184 *
2185 * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/list| Notifications: list}
2186 *
2187 * @param {GetNotificationsOptions} [options] Configuration options.
2188 * @param {string} [options.userProject] The ID of the project which will be
2189 * billed for the request.
2190 * @param {GetNotificationsCallback} [callback] Callback function.
2191 * @returns {Promise<GetNotificationsResponse>}
2192 *
2193 * @example
2194 * ```
2195 * const {Storage} = require('@google-cloud/storage');
2196 * const storage = new Storage();
2197 * const bucket = storage.bucket('my-bucket');
2198 *
2199 * bucket.getNotifications(function(err, notifications, apiResponse) {
2200 * if (!err) {
2201 * // notifications is an array of Notification objects.
2202 * }
2203 * });
2204 *
2205 * //-
2206 * // If the callback is omitted, we'll return a Promise.
2207 * //-
2208 * bucket.getNotifications().then(function(data) {
2209 * const notifications = data[0];
2210 * const apiResponse = data[1];
2211 * });
2212 *
2213 * ```
2214 * @example <caption>include:samples/listNotifications.js</caption>
2215 * region_tag:storage_list_bucket_notifications
2216 * Another example:
2217 */
2218 getNotifications(optionsOrCallback, callback) {
2219 let options = {};
2220 if (typeof optionsOrCallback === 'function') {
2221 callback = optionsOrCallback;
2222 }
2223 else if (optionsOrCallback) {
2224 options = optionsOrCallback;
2225 }
2226 this.request({
2227 uri: '/notificationConfigs',
2228 qs: options,
2229 }, (err, resp) => {
2230 if (err) {
2231 callback(err, null, resp);
2232 return;
2233 }
2234 const itemsArray = resp.items ? resp.items : [];
2235 const notifications = itemsArray.map((notification) => {
2236 const notificationInstance = this.notification(notification.id);
2237 notificationInstance.metadata = notification;
2238 return notificationInstance;
2239 });
2240 callback(null, notifications, resp);
2241 });
2242 }
2243 /**
2244 * @typedef {array} GetSignedUrlResponse
2245 * @property {object} 0 The signed URL.
2246 */
2247 /**
2248 * @callback GetSignedUrlCallback
2249 * @param {?Error} err Request error, if any.
2250 * @param {object} url The signed URL.
2251 */
2252 /**
2253 * @typedef {object} GetBucketSignedUrlConfig
2254 * @property {string} action Only listing objects within a bucket (HTTP: GET) is supported for bucket-level signed URLs.
2255 * @property {*} expires A timestamp when this link will expire. Any value
2256 * given is passed to `new Date()`.
2257 * Note: 'v4' supports maximum duration of 7 days (604800 seconds) from now.
2258 * @property {string} [version='v2'] The signing version to use, either
2259 * 'v2' or 'v4'.
2260 * @property {boolean} [virtualHostedStyle=false] Use virtual hosted-style
2261 * URLs ('https://mybucket.storage.googleapis.com/...') instead of path-style
2262 * ('https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs
2263 * should generally be preferred instaed of path-style URL.
2264 * Currently defaults to `false` for path-style, although this may change in a
2265 * future major-version release.
2266 * @property {string} [cname] The cname for this bucket, i.e.,
2267 * "https://cdn.example.com".
2268 * See [reference]{@link https://cloud.google.com/storage/docs/access-control/signed-urls#example}
2269 * @property {object} [extensionHeaders] If these headers are used, the
2270 * server will check to make sure that the client provides matching
2271 * values. See {@link https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers| Canonical extension headers}
2272 * for the requirements of this feature, most notably:
2273 * - The header name must be prefixed with `x-goog-`
2274 * - The header name must be all lowercase
2275 *
2276 * Note: Multi-valued header passed as an array in the extensionHeaders
2277 * object is converted into a string, delimited by `,` with
2278 * no space. Requests made using the signed URL will need to
2279 * delimit multi-valued headers using a single `,` as well, or
2280 * else the server will report a mismatched signature.
2281 * @property {object} [queryParams] Additional query parameters to include
2282 * in the signed URL.
2283 */
2284 /**
2285 * Get a signed URL to allow limited time access to a bucket.
2286 *
2287 * In Google Cloud Platform environments, such as Cloud Functions and App
2288 * Engine, you usually don't provide a `keyFilename` or `credentials` during
2289 * instantiation. In those environments, we call the
2290 * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob| signBlob API}
2291 * to create a signed URL. That API requires either the
2292 * `https://www.googleapis.com/auth/iam` or
2293 * `https://www.googleapis.com/auth/cloud-platform` scope, so be sure they are
2294 * enabled.
2295 *
2296 * See {@link https://cloud.google.com/storage/docs/access-control/signed-urls| Signed URLs Reference}
2297 *
2298 * @throws {Error} if an expiration timestamp from the past is given.
2299 *
2300 * @param {GetBucketSignedUrlConfig} config Configuration object.
2301 * @param {string} config.action Currently only supports "list" (HTTP: GET).
2302 * @param {*} config.expires A timestamp when this link will expire. Any value
2303 * given is passed to `new Date()`.
2304 * Note: 'v4' supports maximum duration of 7 days (604800 seconds) from now.
2305 * @param {string} [config.version='v2'] The signing version to use, either
2306 * 'v2' or 'v4'.
2307 * @param {boolean} [config.virtualHostedStyle=false] Use virtual hosted-style
2308 * URLs ('https://mybucket.storage.googleapis.com/...') instead of path-style
2309 * ('https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs
2310 * should generally be preferred instaed of path-style URL.
2311 * Currently defaults to `false` for path-style, although this may change in a
2312 * future major-version release.
2313 * @param {string} [config.cname] The cname for this bucket, i.e.,
2314 * "https://cdn.example.com".
2315 * See [reference]{@link https://cloud.google.com/storage/docs/access-control/signed-urls#example}
2316 * @param {object} [config.extensionHeaders] If these headers are used, the
2317 * server will check to make sure that the client provides matching
2318 * values. See {@link https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers| Canonical extension headers}
2319 * for the requirements of this feature, most notably:
2320 * - The header name must be prefixed with `x-goog-`
2321 * - The header name must be all lowercase
2322 *
2323 * Note: Multi-valued header passed as an array in the extensionHeaders
2324 * object is converted into a string, delimited by `,` with
2325 * no space. Requests made using the signed URL will need to
2326 * delimit multi-valued headers using a single `,` as well, or
2327 * else the server will report a mismatched signature.
2328 * @property {object} [config.queryParams] Additional query parameters to include
2329 * in the signed URL.
2330 * @param {GetSignedUrlCallback} [callback] Callback function.
2331 * @returns {Promise<GetSignedUrlResponse>}
2332 *
2333 * @example
2334 * ```
2335 * const {Storage} = require('@google-cloud/storage');
2336 * const storage = new Storage();
2337 * const myBucket = storage.bucket('my-bucket');
2338 *
2339 * //-
2340 * // Generate a URL that allows temporary access to list files in a bucket.
2341 * //-
2342 * const request = require('request');
2343 *
2344 * const config = {
2345 * action: 'list',
2346 * expires: '03-17-2025'
2347 * };
2348 *
2349 * bucket.getSignedUrl(config, function(err, url) {
2350 * if (err) {
2351 * console.error(err);
2352 * return;
2353 * }
2354 *
2355 * // The bucket is now available to be listed from this URL.
2356 * request(url, function(err, resp) {
2357 * // resp.statusCode = 200
2358 * });
2359 * });
2360 *
2361 * //-
2362 * // If the callback is omitted, we'll return a Promise.
2363 * //-
2364 * bucket.getSignedUrl(config).then(function(data) {
2365 * const url = data[0];
2366 * });
2367 * ```
2368 */
2369 getSignedUrl(cfg, callback) {
2370 const method = BucketActionToHTTPMethod[cfg.action];
2371 const signConfig = {
2372 method,
2373 expires: cfg.expires,
2374 version: cfg.version,
2375 cname: cfg.cname,
2376 extensionHeaders: cfg.extensionHeaders || {},
2377 queryParams: cfg.queryParams || {},
2378 host: cfg.host,
2379 signingEndpoint: cfg.signingEndpoint,
2380 };
2381 if (!this.signer) {
2382 this.signer = new URLSigner(this.storage.authClient, this, undefined, this.storage);
2383 }
2384 this.signer
2385 .getSignedUrl(signConfig)
2386 .then(signedUrl => callback(null, signedUrl), callback);
2387 }
2388 /**
2389 * @callback BucketLockCallback
2390 * @param {?Error} err Request error, if any.
2391 * @param {object} apiResponse The full API response.
2392 */
2393 /**
2394 * Lock a previously-defined retention policy. This will prevent changes to
2395 * the policy.
2396 *
2397 * @throws {Error} if a metageneration is not provided.
2398 *
2399 * @param {number|string} metageneration The bucket's metageneration. This is
2400 * accesssible from calling {@link File#getMetadata}.
2401 * @param {BucketLockCallback} [callback] Callback function.
2402 * @returns {Promise<BucketLockResponse>}
2403 *
2404 * @example
2405 * ```
2406 * const storage = require('@google-cloud/storage')();
2407 * const bucket = storage.bucket('albums');
2408 *
2409 * const metageneration = 2;
2410 *
2411 * bucket.lock(metageneration, function(err, apiResponse) {});
2412 *
2413 * //-
2414 * // If the callback is omitted, we'll return a Promise.
2415 * //-
2416 * bucket.lock(metageneration).then(function(data) {
2417 * const apiResponse = data[0];
2418 * });
2419 * ```
2420 */
2421 lock(metageneration, callback) {
2422 const metatype = typeof metageneration;
2423 if (metatype !== 'number' && metatype !== 'string') {
2424 throw new Error(BucketExceptionMessages.METAGENERATION_NOT_PROVIDED);
2425 }
2426 this.request({
2427 method: 'POST',
2428 uri: '/lockRetentionPolicy',
2429 qs: {
2430 ifMetagenerationMatch: metageneration,
2431 },
2432 }, callback);
2433 }
2434 /**
2435 * @typedef {array} MakeBucketPrivateResponse
2436 * @property {File[]} 0 List of files made private.
2437 */
2438 /**
2439 * @callback MakeBucketPrivateCallback
2440 * @param {?Error} err Request error, if any.
2441 * @param {File[]} files List of files made private.
2442 */
2443 /**
2444 * @typedef {object} MakeBucketPrivateOptions
2445 * @property {boolean} [includeFiles=false] Make each file in the bucket
2446 * private.
2447 * @property {Metadata} [metadata] Define custom metadata properties to define
2448 * along with the operation.
2449 * @property {boolean} [force] Queue errors occurred while making files
2450 * private until all files have been processed.
2451 * @property {string} [userProject] The ID of the project which will be
2452 * billed for the request.
2453 */
2454 /**
2455 * Make the bucket listing private.
2456 *
2457 * You may also choose to make the contents of the bucket private by
2458 * specifying `includeFiles: true`. This will automatically run
2459 * {@link File#makePrivate} for every file in the bucket.
2460 *
2461 * When specifying `includeFiles: true`, use `force: true` to delay execution
2462 * of your callback until all files have been processed. By default, the
2463 * callback is executed after the first error. Use `force` to queue such
2464 * errors until all files have been processed, after which they will be
2465 * returned as an array as the first argument to your callback.
2466 *
2467 * NOTE: This may cause the process to be long-running and use a high number
2468 * of requests. Use with caution.
2469 *
2470 * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation}
2471 *
2472 * @param {MakeBucketPrivateOptions} [options] Configuration options.
2473 * @param {boolean} [options.includeFiles=false] Make each file in the bucket
2474 * private.
2475 * @param {Metadata} [options.metadata] Define custom metadata properties to define
2476 * along with the operation.
2477 * @param {boolean} [options.force] Queue errors occurred while making files
2478 * private until all files have been processed.
2479 * @param {string} [options.userProject] The ID of the project which will be
2480 * billed for the request.
2481 * @param {MakeBucketPrivateCallback} [callback] Callback function.
2482 * @returns {Promise<MakeBucketPrivateResponse>}
2483 *
2484 * @example
2485 * ```
2486 * const {Storage} = require('@google-cloud/storage');
2487 * const storage = new Storage();
2488 * const bucket = storage.bucket('albums');
2489 *
2490 * //-
2491 * // Make the bucket private.
2492 * //-
2493 * bucket.makePrivate(function(err) {});
2494 *
2495 * //-
2496 * // Make the bucket and its contents private.
2497 * //-
2498 * const opts = {
2499 * includeFiles: true
2500 * };
2501 *
2502 * bucket.makePrivate(opts, function(err, files) {
2503 * // `err`:
2504 * // The first error to occur, otherwise null.
2505 * //
2506 * // `files`:
2507 * // Array of files successfully made private in the bucket.
2508 * });
2509 *
2510 * //-
2511 * // Make the bucket and its contents private, using force to suppress errors
2512 * // until all files have been processed.
2513 * //-
2514 * const opts = {
2515 * includeFiles: true,
2516 * force: true
2517 * };
2518 *
2519 * bucket.makePrivate(opts, function(errors, files) {
2520 * // `errors`:
2521 * // Array of errors if any occurred, otherwise null.
2522 * //
2523 * // `files`:
2524 * // Array of files successfully made private in the bucket.
2525 * });
2526 *
2527 * //-
2528 * // If the callback is omitted, we'll return a Promise.
2529 * //-
2530 * bucket.makePrivate(opts).then(function(data) {
2531 * const files = data[0];
2532 * });
2533 * ```
2534 */
2535 makePrivate(optionsOrCallback, callback) {
2536 var _a, _b, _c, _d;
2537 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
2538 callback =
2539 typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
2540 options.private = true;
2541 const query = {
2542 predefinedAcl: 'projectPrivate',
2543 };
2544 if (options.userProject) {
2545 query.userProject = options.userProject;
2546 }
2547 if ((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) {
2548 query.ifGenerationMatch = options.preconditionOpts.ifGenerationMatch;
2549 }
2550 if ((_b = options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationNotMatch) {
2551 query.ifGenerationNotMatch =
2552 options.preconditionOpts.ifGenerationNotMatch;
2553 }
2554 if ((_c = options.preconditionOpts) === null || _c === void 0 ? void 0 : _c.ifMetagenerationMatch) {
2555 query.ifMetagenerationMatch =
2556 options.preconditionOpts.ifMetagenerationMatch;
2557 }
2558 if ((_d = options.preconditionOpts) === null || _d === void 0 ? void 0 : _d.ifMetagenerationNotMatch) {
2559 query.ifMetagenerationNotMatch =
2560 options.preconditionOpts.ifMetagenerationNotMatch;
2561 }
2562 // You aren't allowed to set both predefinedAcl & acl properties on a bucket
2563 // so acl must explicitly be nullified.
2564 const metadata = { ...options.metadata, acl: null };
2565 this.setMetadata(metadata, query, (err) => {
2566 if (err) {
2567 callback(err);
2568 }
2569 const internalCall = () => {
2570 if (options.includeFiles) {
2571 return promisify(this.makeAllFilesPublicPrivate_).call(this, options);
2572 }
2573 return Promise.resolve([]);
2574 };
2575 internalCall()
2576 .then(files => callback(null, files))
2577 .catch(callback);
2578 });
2579 }
2580 /**
2581 * @typedef {object} MakeBucketPublicOptions
2582 * @property {boolean} [includeFiles=false] Make each file in the bucket
2583 * private.
2584 * @property {boolean} [force] Queue errors occurred while making files
2585 * private until all files have been processed.
2586 */
2587 /**
2588 * @callback MakeBucketPublicCallback
2589 * @param {?Error} err Request error, if any.
2590 * @param {File[]} files List of files made public.
2591 */
2592 /**
2593 * @typedef {array} MakeBucketPublicResponse
2594 * @property {File[]} 0 List of files made public.
2595 */
2596 /**
2597 * Make the bucket publicly readable.
2598 *
2599 * You may also choose to make the contents of the bucket publicly readable by
2600 * specifying `includeFiles: true`. This will automatically run
2601 * {@link File#makePublic} for every file in the bucket.
2602 *
2603 * When specifying `includeFiles: true`, use `force: true` to delay execution
2604 * of your callback until all files have been processed. By default, the
2605 * callback is executed after the first error. Use `force` to queue such
2606 * errors until all files have been processed, after which they will be
2607 * returned as an array as the first argument to your callback.
2608 *
2609 * NOTE: This may cause the process to be long-running and use a high number
2610 * of requests. Use with caution.
2611 *
2612 * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation}
2613 *
2614 * @param {MakeBucketPublicOptions} [options] Configuration options.
2615 * @param {boolean} [options.includeFiles=false] Make each file in the bucket
2616 * private.
2617 * @param {boolean} [options.force] Queue errors occurred while making files
2618 * private until all files have been processed.
2619 * @param {MakeBucketPublicCallback} [callback] Callback function.
2620 * @returns {Promise<MakeBucketPublicResponse>}
2621 *
2622 * @example
2623 * ```
2624 * const {Storage} = require('@google-cloud/storage');
2625 * const storage = new Storage();
2626 * const bucket = storage.bucket('albums');
2627 *
2628 * //-
2629 * // Make the bucket publicly readable.
2630 * //-
2631 * bucket.makePublic(function(err) {});
2632 *
2633 * //-
2634 * // Make the bucket and its contents publicly readable.
2635 * //-
2636 * const opts = {
2637 * includeFiles: true
2638 * };
2639 *
2640 * bucket.makePublic(opts, function(err, files) {
2641 * // `err`:
2642 * // The first error to occur, otherwise null.
2643 * //
2644 * // `files`:
2645 * // Array of files successfully made public in the bucket.
2646 * });
2647 *
2648 * //-
2649 * // Make the bucket and its contents publicly readable, using force to
2650 * // suppress errors until all files have been processed.
2651 * //-
2652 * const opts = {
2653 * includeFiles: true,
2654 * force: true
2655 * };
2656 *
2657 * bucket.makePublic(opts, function(errors, files) {
2658 * // `errors`:
2659 * // Array of errors if any occurred, otherwise null.
2660 * //
2661 * // `files`:
2662 * // Array of files successfully made public in the bucket.
2663 * });
2664 *
2665 * //-
2666 * // If the callback is omitted, we'll return a Promise.
2667 * //-
2668 * bucket.makePublic(opts).then(function(data) {
2669 * const files = data[0];
2670 * });
2671 * ```
2672 */
2673 makePublic(optionsOrCallback, callback) {
2674 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
2675 callback =
2676 typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
2677 const req = { public: true, ...options };
2678 this.acl
2679 .add({
2680 entity: 'allUsers',
2681 role: 'READER',
2682 })
2683 .then(() => {
2684 return this.acl.default.add({
2685 entity: 'allUsers',
2686 role: 'READER',
2687 });
2688 })
2689 .then(() => {
2690 if (req.includeFiles) {
2691 return promisify(this.makeAllFilesPublicPrivate_).call(this, req);
2692 }
2693 return [];
2694 })
2695 .then(files => callback(null, files), callback);
2696 }
2697 /**
2698 * Get a reference to a Cloud Pub/Sub Notification.
2699 *
2700 * @param {string} id ID of notification.
2701 * @returns {Notification}
2702 * @see Notification
2703 *
2704 * @example
2705 * ```
2706 * const {Storage} = require('@google-cloud/storage');
2707 * const storage = new Storage();
2708 * const bucket = storage.bucket('my-bucket');
2709 * const notification = bucket.notification('1');
2710 * ```
2711 */
2712 notification(id) {
2713 if (!id) {
2714 throw new Error(BucketExceptionMessages.SUPPLY_NOTIFICATION_ID);
2715 }
2716 return new Notification(this, id);
2717 }
2718 /**
2719 * Remove an already-existing retention policy from this bucket, if it is not
2720 * locked.
2721 *
2722 * @param {SetBucketMetadataCallback} [callback] Callback function.
2723 * @param {SetBucketMetadataOptions} [options] Options, including precondition options
2724 * @returns {Promise<SetBucketMetadataResponse>}
2725 *
2726 * @example
2727 * ```
2728 * const storage = require('@google-cloud/storage')();
2729 * const bucket = storage.bucket('albums');
2730 *
2731 * bucket.removeRetentionPeriod(function(err, apiResponse) {});
2732 *
2733 * //-
2734 * // If the callback is omitted, we'll return a Promise.
2735 * //-
2736 * bucket.removeRetentionPeriod().then(function(data) {
2737 * const apiResponse = data[0];
2738 * });
2739 * ```
2740 */
2741 removeRetentionPeriod(optionsOrCallback, callback) {
2742 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
2743 callback =
2744 typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
2745 this.setMetadata({
2746 retentionPolicy: null,
2747 }, options, callback);
2748 }
2749 /**
2750 * Makes request and applies userProject query parameter if necessary.
2751 *
2752 * @private
2753 *
2754 * @param {object} reqOpts - The request options.
2755 * @param {function} callback - The callback function.
2756 */
2757 request(reqOpts, callback) {
2758 if (this.userProject && (!reqOpts.qs || !reqOpts.qs.userProject)) {
2759 reqOpts.qs = { ...reqOpts.qs, userProject: this.userProject };
2760 }
2761 return super.request(reqOpts, callback);
2762 }
2763 /**
2764 * @deprecated
2765 * @typedef {array} SetLabelsResponse
2766 * @property {object} 0 The bucket metadata.
2767 */
2768 /**
2769 * @deprecated
2770 * @callback SetLabelsCallback
2771 * @param {?Error} err Request error, if any.
2772 * @param {object} metadata The bucket metadata.
2773 */
2774 /**
2775 * @deprecated
2776 * @typedef {object} SetLabelsOptions Configuration options for Bucket#setLabels().
2777 * @property {string} [userProject] The ID of the project which will be
2778 * billed for the request.
2779 */
2780 /**
2781 * @deprecated Use setMetadata directly.
2782 * Set labels on the bucket.
2783 *
2784 * This makes an underlying call to {@link Bucket#setMetadata}, which
2785 * is a PATCH request. This means an individual label can be overwritten, but
2786 * unmentioned labels will not be touched.
2787 *
2788 * @param {object<string, string>} labels Labels to set on the bucket.
2789 * @param {SetLabelsOptions} [options] Configuration options.
2790 * @param {string} [options.userProject] The ID of the project which will be
2791 * billed for the request.
2792 * @param {SetLabelsCallback} [callback] Callback function.
2793 * @returns {Promise<SetLabelsResponse>}
2794 *
2795 * @example
2796 * ```
2797 * const {Storage} = require('@google-cloud/storage');
2798 * const storage = new Storage();
2799 * const bucket = storage.bucket('albums');
2800 *
2801 * const labels = {
2802 * labelone: 'labelonevalue',
2803 * labeltwo: 'labeltwovalue'
2804 * };
2805 *
2806 * bucket.setLabels(labels, function(err, metadata) {
2807 * if (!err) {
2808 * // Labels set successfully.
2809 * }
2810 * });
2811 *
2812 * //-
2813 * // If the callback is omitted, we'll return a Promise.
2814 * //-
2815 * bucket.setLabels(labels).then(function(data) {
2816 * const metadata = data[0];
2817 * });
2818 * ```
2819 */
2820 setLabels(labels, optionsOrCallback, callback) {
2821 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
2822 callback =
2823 typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
2824 callback = callback || util.noop;
2825 this.setMetadata({ labels }, options, callback);
2826 }
2827 setMetadata(metadata, optionsOrCallback, cb) {
2828 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
2829 cb =
2830 typeof optionsOrCallback === 'function'
2831 ? optionsOrCallback
2832 : cb;
2833 this.disableAutoRetryConditionallyIdempotent_(this.methods.setMetadata, AvailableServiceObjectMethods.setMetadata, options);
2834 super
2835 .setMetadata(metadata, options)
2836 .then(resp => cb(null, ...resp))
2837 .catch(cb)
2838 .finally(() => {
2839 this.storage.retryOptions.autoRetry = this.instanceRetryValue;
2840 });
2841 }
2842 /**
2843 * Lock all objects contained in the bucket, based on their creation time. Any
2844 * attempt to overwrite or delete objects younger than the retention period
2845 * will result in a `PERMISSION_DENIED` error.
2846 *
2847 * An unlocked retention policy can be modified or removed from the bucket via
2848 * {@link File#removeRetentionPeriod} and {@link File#setRetentionPeriod}. A
2849 * locked retention policy cannot be removed or shortened in duration for the
2850 * lifetime of the bucket. Attempting to remove or decrease period of a locked
2851 * retention policy will result in a `PERMISSION_DENIED` error. You can still
2852 * increase the policy.
2853 *
2854 * @param {*} duration In seconds, the minimum retention time for all objects
2855 * contained in this bucket.
2856 * @param {SetBucketMetadataCallback} [callback] Callback function.
2857 * @param {SetBucketMetadataCallback} [options] Options, including precondition options.
2858 * @returns {Promise<SetBucketMetadataResponse>}
2859 *
2860 * @example
2861 * ```
2862 * const storage = require('@google-cloud/storage')();
2863 * const bucket = storage.bucket('albums');
2864 *
2865 * const DURATION_SECONDS = 15780000; // 6 months.
2866 *
2867 * //-
2868 * // Lock the objects in this bucket for 6 months.
2869 * //-
2870 * bucket.setRetentionPeriod(DURATION_SECONDS, function(err, apiResponse) {});
2871 *
2872 * //-
2873 * // If the callback is omitted, we'll return a Promise.
2874 * //-
2875 * bucket.setRetentionPeriod(DURATION_SECONDS).then(function(data) {
2876 * const apiResponse = data[0];
2877 * });
2878 * ```
2879 */
2880 setRetentionPeriod(duration, optionsOrCallback, callback) {
2881 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
2882 callback =
2883 typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
2884 this.setMetadata({
2885 retentionPolicy: {
2886 retentionPeriod: duration.toString(),
2887 },
2888 }, options, callback);
2889 }
2890 /**
2891 *
2892 * @typedef {object} Cors
2893 * @property {number} [maxAgeSeconds] The number of seconds the browser is
2894 * allowed to make requests before it must repeat the preflight request.
2895 * @property {string[]} [method] HTTP method allowed for cross origin resource
2896 * sharing with this bucket.
2897 * @property {string[]} [origin] an origin allowed for cross origin resource
2898 * sharing with this bucket.
2899 * @property {string[]} [responseHeader] A header allowed for cross origin
2900 * resource sharing with this bucket.
2901 */
2902 /**
2903 * This can be used to set the CORS configuration on the bucket.
2904 *
2905 * The configuration will be overwritten with the value passed into this.
2906 *
2907 * @param {Cors[]} corsConfiguration The new CORS configuration to set
2908 * @param {number} [corsConfiguration.maxAgeSeconds] The number of seconds the browser is
2909 * allowed to make requests before it must repeat the preflight request.
2910 * @param {string[]} [corsConfiguration.method] HTTP method allowed for cross origin resource
2911 * sharing with this bucket.
2912 * @param {string[]} [corsConfiguration.origin] an origin allowed for cross origin resource
2913 * sharing with this bucket.
2914 * @param {string[]} [corsConfiguration.responseHeader] A header allowed for cross origin
2915 * resource sharing with this bucket.
2916 * @param {SetBucketMetadataCallback} [callback] Callback function.
2917 * @param {SetBucketMetadataOptions} [options] Options, including precondition options.
2918 * @returns {Promise<SetBucketMetadataResponse>}
2919 *
2920 * @example
2921 * ```
2922 * const storage = require('@google-cloud/storage')();
2923 * const bucket = storage.bucket('albums');
2924 *
2925 * const corsConfiguration = [{maxAgeSeconds: 3600}]; // 1 hour
2926 * bucket.setCorsConfiguration(corsConfiguration);
2927 *
2928 * //-
2929 * // If the callback is omitted, we'll return a Promise.
2930 * //-
2931 * bucket.setCorsConfiguration(corsConfiguration).then(function(data) {
2932 * const apiResponse = data[0];
2933 * });
2934 * ```
2935 */
2936 setCorsConfiguration(corsConfiguration, optionsOrCallback, callback) {
2937 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
2938 callback =
2939 typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
2940 this.setMetadata({
2941 cors: corsConfiguration,
2942 }, options, callback);
2943 }
2944 /**
2945 * @typedef {object} SetBucketStorageClassOptions
2946 * @property {string} [userProject] - The ID of the project which will be
2947 * billed for the request.
2948 */
2949 /**
2950 * @callback SetBucketStorageClassCallback
2951 * @param {?Error} err Request error, if any.
2952 */
2953 /**
2954 * Set the default storage class for new files in this bucket.
2955 *
2956 * See {@link https://cloud.google.com/storage/docs/storage-classes| Storage Classes}
2957 *
2958 * @param {string} storageClass The new storage class. (`standard`,
2959 * `nearline`, `coldline`, or `archive`).
2960 * **Note:** The storage classes `multi_regional`, `regional`, and
2961 * `durable_reduced_availability` are now legacy and will be deprecated in
2962 * the future.
2963 * @param {object} [options] Configuration options.
2964 * @param {string} [options.userProject] - The ID of the project which will be
2965 * billed for the request.
2966 * @param {SetStorageClassCallback} [callback] Callback function.
2967 * @returns {Promise}
2968 *
2969 * @example
2970 * ```
2971 * const {Storage} = require('@google-cloud/storage');
2972 * const storage = new Storage();
2973 * const bucket = storage.bucket('albums');
2974 *
2975 * bucket.setStorageClass('nearline', function(err, apiResponse) {
2976 * if (err) {
2977 * // Error handling omitted.
2978 * }
2979 *
2980 * // The storage class was updated successfully.
2981 * });
2982 *
2983 * //-
2984 * // If the callback is omitted, we'll return a Promise.
2985 * //-
2986 * bucket.setStorageClass('nearline').then(function() {});
2987 * ```
2988 */
2989 setStorageClass(storageClass, optionsOrCallback, callback) {
2990 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
2991 callback =
2992 typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
2993 // In case we get input like `storageClass`, convert to `storage_class`.
2994 storageClass = storageClass
2995 .replace(/-/g, '_')
2996 .replace(/([a-z])([A-Z])/g, (_, low, up) => {
2997 return low + '_' + up;
2998 })
2999 .toUpperCase();
3000 this.setMetadata({ storageClass }, options, callback);
3001 }
3002 /**
3003 * Set a user project to be billed for all requests made from this Bucket
3004 * object and any files referenced from this Bucket object.
3005 *
3006 * @param {string} userProject The user project.
3007 *
3008 * @example
3009 * ```
3010 * const {Storage} = require('@google-cloud/storage');
3011 * const storage = new Storage();
3012 * const bucket = storage.bucket('albums');
3013 *
3014 * bucket.setUserProject('grape-spaceship-123');
3015 * ```
3016 */
3017 setUserProject(userProject) {
3018 this.userProject = userProject;
3019 const methods = [
3020 'create',
3021 'delete',
3022 'exists',
3023 'get',
3024 'getMetadata',
3025 'setMetadata',
3026 ];
3027 methods.forEach(method => {
3028 const methodConfig = this.methods[method];
3029 if (typeof methodConfig === 'object') {
3030 if (typeof methodConfig.reqOpts === 'object') {
3031 Object.assign(methodConfig.reqOpts.qs, { userProject });
3032 }
3033 else {
3034 methodConfig.reqOpts = {
3035 qs: { userProject },
3036 };
3037 }
3038 }
3039 });
3040 }
3041 /**
3042 * @typedef {object} UploadOptions Configuration options for Bucket#upload().
3043 * @property {string|File} [destination] The place to save
3044 * your file. If given a string, the file will be uploaded to the bucket
3045 * using the string as a filename. When given a File object, your local
3046 * file will be uploaded to the File object's bucket and under the File
3047 * object's name. Lastly, when this argument is omitted, the file is uploaded
3048 * to your bucket using the name of the local file.
3049 * @property {string} [encryptionKey] A custom encryption key. See
3050 * {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys}.
3051 * @property {boolean} [gzip] Automatically gzip the file. This will set
3052 * `options.metadata.contentEncoding` to `gzip`.
3053 * @property {string} [kmsKeyName] The name of the Cloud KMS key that will
3054 * be used to encrypt the object. Must be in the format:
3055 * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`.
3056 * @property {object} [metadata] See an
3057 * {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON| Objects: insert request body}.
3058 * @property {string} [offset] The starting byte of the upload stream, for
3059 * resuming an interrupted upload. Defaults to 0.
3060 * @property {string} [predefinedAcl] Apply a predefined set of access
3061 * controls to this object.
3062 *
3063 * Acceptable values are:
3064 * - **`authenticatedRead`** - Object owner gets `OWNER` access, and
3065 * `allAuthenticatedUsers` get `READER` access.
3066 *
3067 * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and
3068 * project team owners get `OWNER` access.
3069 *
3070 * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project
3071 * team owners get `READER` access.
3072 *
3073 * - **`private`** - Object owner gets `OWNER` access.
3074 *
3075 * - **`projectPrivate`** - Object owner gets `OWNER` access, and project
3076 * team members get access according to their roles.
3077 *
3078 * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers`
3079 * get `READER` access.
3080 * @property {boolean} [private] Make the uploaded file private. (Alias for
3081 * `options.predefinedAcl = 'private'`)
3082 * @property {boolean} [public] Make the uploaded file public. (Alias for
3083 * `options.predefinedAcl = 'publicRead'`)
3084 * @property {boolean} [resumable=true] Resumable uploads are automatically
3085 * enabled and must be shut off explicitly by setting to false.
3086 * @property {number} [timeout=60000] Set the HTTP request timeout in
3087 * milliseconds. This option is not available for resumable uploads.
3088 * Default: `60000`
3089 * @property {string} [uri] The URI for an already-created resumable
3090 * upload. See {@link File#createResumableUpload}.
3091 * @property {string} [userProject] The ID of the project which will be
3092 * billed for the request.
3093 * @property {string|boolean} [validation] Possible values: `"md5"`,
3094 * `"crc32c"`, or `false`. By default, data integrity is validated with an
3095 * MD5 checksum for maximum reliability. CRC32c will provide better
3096 * performance with less reliability. You may also choose to skip
3097 * validation completely, however this is **not recommended**.
3098 */
3099 /**
3100 * @typedef {array} UploadResponse
3101 * @property {object} 0 The uploaded {@link File}.
3102 * @property {object} 1 The full API response.
3103 */
3104 /**
3105 * @callback UploadCallback
3106 * @param {?Error} err Request error, if any.
3107 * @param {object} file The uploaded {@link File}.
3108 * @param {object} apiResponse The full API response.
3109 */
3110 /**
3111 * Upload a file to the bucket. This is a convenience method that wraps
3112 * {@link File#createWriteStream}.
3113 *
3114 * Resumable uploads are enabled by default
3115 *
3116 * See {@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload#uploads| Upload Options (Simple or Resumable)}
3117 * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert| Objects: insert API Documentation}
3118 *
3119 * @param {string} pathString The fully qualified path to the file you
3120 * wish to upload to your bucket.
3121 * @param {UploadOptions} [options] Configuration options.
3122 * @param {string|File} [options.destination] The place to save
3123 * your file. If given a string, the file will be uploaded to the bucket
3124 * using the string as a filename. When given a File object, your local
3125 * file will be uploaded to the File object's bucket and under the File
3126 * object's name. Lastly, when this argument is omitted, the file is uploaded
3127 * to your bucket using the name of the local file.
3128 * @param {string} [options.encryptionKey] A custom encryption key. See
3129 * {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys}.
3130 * @param {boolean} [options.gzip] Automatically gzip the file. This will set
3131 * `options.metadata.contentEncoding` to `gzip`.
3132 * @param {string} [options.kmsKeyName] The name of the Cloud KMS key that will
3133 * be used to encrypt the object. Must be in the format:
3134 * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`.
3135 * @param {object} [options.metadata] See an
3136 * {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON| Objects: insert request body}.
3137 * @param {string} [options.offset] The starting byte of the upload stream, for
3138 * resuming an interrupted upload. Defaults to 0.
3139 * @param {string} [options.predefinedAcl] Apply a predefined set of access
3140 * controls to this object.
3141 * Acceptable values are:
3142 * - **`authenticatedRead`** - Object owner gets `OWNER` access, and
3143 * `allAuthenticatedUsers` get `READER` access.
3144 *
3145 * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and
3146 * project team owners get `OWNER` access.
3147 *
3148 * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project
3149 * team owners get `READER` access.
3150 *
3151 * - **`private`** - Object owner gets `OWNER` access.
3152 *
3153 * - **`projectPrivate`** - Object owner gets `OWNER` access, and project
3154 * team members get access according to their roles.
3155 *
3156 * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers`
3157 * get `READER` access.
3158 * @param {boolean} [options.private] Make the uploaded file private. (Alias for
3159 * `options.predefinedAcl = 'private'`)
3160 * @param {boolean} [options.public] Make the uploaded file public. (Alias for
3161 * `options.predefinedAcl = 'publicRead'`)
3162 * @param {boolean} [options.resumable=true] Resumable uploads are automatically
3163 * enabled and must be shut off explicitly by setting to false.
3164 * @param {number} [options.timeout=60000] Set the HTTP request timeout in
3165 * milliseconds. This option is not available for resumable uploads.
3166 * Default: `60000`
3167 * @param {string} [options.uri] The URI for an already-created resumable
3168 * upload. See {@link File#createResumableUpload}.
3169 * @param {string} [options.userProject] The ID of the project which will be
3170 * billed for the request.
3171 * @param {string|boolean} [options.validation] Possible values: `"md5"`,
3172 * `"crc32c"`, or `false`. By default, data integrity is validated with an
3173 * MD5 checksum for maximum reliability. CRC32c will provide better
3174 * performance with less reliability. You may also choose to skip
3175 * validation completely, however this is **not recommended**.
3176 * @param {UploadCallback} [callback] Callback function.
3177 * @returns {Promise<UploadResponse>}
3178 *
3179 * @example
3180 * ```
3181 * const {Storage} = require('@google-cloud/storage');
3182 * const storage = new Storage();
3183 * const bucket = storage.bucket('albums');
3184 *
3185 * //-
3186 * // Upload a file from a local path.
3187 * //-
3188 * bucket.upload('/local/path/image.png', function(err, file, apiResponse) {
3189 * // Your bucket now contains:
3190 * // - "image.png" (with the contents of `/local/path/image.png')
3191 *
3192 * // `file` is an instance of a File object that refers to your new file.
3193 * });
3194 *
3195 *
3196 * //-
3197 * // It's not always that easy. You will likely want to specify the filename
3198 * // used when your new file lands in your bucket.
3199 * //
3200 * // You may also want to set metadata or customize other options.
3201 * //-
3202 * const options = {
3203 * destination: 'new-image.png',
3204 * validation: 'crc32c',
3205 * metadata: {
3206 * metadata: {
3207 * event: 'Fall trip to the zoo'
3208 * }
3209 * }
3210 * };
3211 *
3212 * bucket.upload('local-image.png', options, function(err, file) {
3213 * // Your bucket now contains:
3214 * // - "new-image.png" (with the contents of `local-image.png')
3215 *
3216 * // `file` is an instance of a File object that refers to your new file.
3217 * });
3218 *
3219 * //-
3220 * // You can also have a file gzip'd on the fly.
3221 * //-
3222 * bucket.upload('index.html', { gzip: true }, function(err, file) {
3223 * // Your bucket now contains:
3224 * // - "index.html" (automatically compressed with gzip)
3225 *
3226 * // Downloading the file with `file.download` will automatically decode
3227 * the
3228 * // file.
3229 * });
3230 *
3231 * //-
3232 * // You may also re-use a File object, {File}, that references
3233 * // the file you wish to create or overwrite.
3234 * //-
3235 * const options = {
3236 * destination: bucket.file('existing-file.png'),
3237 * resumable: false
3238 * };
3239 *
3240 * bucket.upload('local-img.png', options, function(err, newFile) {
3241 * // Your bucket now contains:
3242 * // - "existing-file.png" (with the contents of `local-img.png')
3243 *
3244 * // Note:
3245 * // The `newFile` parameter is equal to `file`.
3246 * });
3247 *
3248 * //-
3249 * // To use
3250 * // <a
3251 * href="https://cloud.google.com/storage/docs/encryption#customer-supplied">
3252 * // Customer-supplied Encryption Keys</a>, provide the `encryptionKey`
3253 * option.
3254 * //-
3255 * const crypto = require('crypto');
3256 * const encryptionKey = crypto.randomBytes(32);
3257 *
3258 * bucket.upload('img.png', {
3259 * encryptionKey: encryptionKey
3260 * }, function(err, newFile) {
3261 * // `img.png` was uploaded with your custom encryption key.
3262 *
3263 * // `newFile` is already configured to use the encryption key when making
3264 * // operations on the remote object.
3265 *
3266 * // However, to use your encryption key later, you must create a `File`
3267 * // instance with the `key` supplied:
3268 * const file = bucket.file('img.png', {
3269 * encryptionKey: encryptionKey
3270 * });
3271 *
3272 * // Or with `file#setEncryptionKey`:
3273 * const file = bucket.file('img.png');
3274 * file.setEncryptionKey(encryptionKey);
3275 * });
3276 *
3277 * //-
3278 * // If the callback is omitted, we'll return a Promise.
3279 * //-
3280 * bucket.upload('local-image.png').then(function(data) {
3281 * const file = data[0];
3282 * });
3283 *
3284 * To upload a file from a URL, use {@link File#createWriteStream}.
3285 *
3286 * ```
3287 * @example <caption>include:samples/files.js</caption>
3288 * region_tag:storage_upload_file
3289 * Another example:
3290 *
3291 * @example <caption>include:samples/encryption.js</caption>
3292 * region_tag:storage_upload_encrypted_file
3293 * Example of uploading an encrypted file:
3294 */
3295 upload(pathString, optionsOrCallback, callback) {
3296 var _a, _b;
3297 const upload = (numberOfRetries) => {
3298 const returnValue = AsyncRetry(async (bail) => {
3299 await new Promise((resolve, reject) => {
3300 var _a, _b;
3301 if (numberOfRetries === 0 &&
3302 ((_b = (_a = newFile === null || newFile === void 0 ? void 0 : newFile.storage) === null || _a === void 0 ? void 0 : _a.retryOptions) === null || _b === void 0 ? void 0 : _b.autoRetry)) {
3303 newFile.storage.retryOptions.autoRetry = false;
3304 }
3305 const writable = newFile.createWriteStream(options);
3306 if (options.onUploadProgress) {
3307 writable.on('progress', options.onUploadProgress);
3308 }
3309 fs.createReadStream(pathString)
3310 .on('error', bail)
3311 .pipe(writable)
3312 .on('error', err => {
3313 if (this.storage.retryOptions.autoRetry &&
3314 this.storage.retryOptions.retryableErrorFn(err)) {
3315 return reject(err);
3316 }
3317 else {
3318 return bail(err);
3319 }
3320 })
3321 .on('finish', () => {
3322 return resolve();
3323 });
3324 });
3325 }, {
3326 retries: numberOfRetries,
3327 factor: this.storage.retryOptions.retryDelayMultiplier,
3328 maxTimeout: this.storage.retryOptions.maxRetryDelay * 1000, //convert to milliseconds
3329 maxRetryTime: this.storage.retryOptions.totalTimeout * 1000, //convert to milliseconds
3330 });
3331 if (!callback) {
3332 return returnValue;
3333 }
3334 else {
3335 return returnValue
3336 .then(() => {
3337 if (callback) {
3338 return callback(null, newFile, newFile.metadata);
3339 }
3340 })
3341 .catch(callback);
3342 }
3343 };
3344 // eslint-disable-next-line @typescript-eslint/no-explicit-any
3345 if (global['GCLOUD_SANDBOX_ENV']) {
3346 return;
3347 }
3348 let options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
3349 callback =
3350 typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
3351 options = Object.assign({
3352 metadata: {},
3353 }, options);
3354 // Do not retry if precondition option ifGenerationMatch is not set
3355 // because this is a file operation
3356 let maxRetries = this.storage.retryOptions.maxRetries;
3357 if ((((_a = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) === undefined &&
3358 ((_b = this.instancePreconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch) === undefined &&
3359 this.storage.retryOptions.idempotencyStrategy ===
3360 IdempotencyStrategy.RetryConditional) ||
3361 this.storage.retryOptions.idempotencyStrategy ===
3362 IdempotencyStrategy.RetryNever) {
3363 maxRetries = 0;
3364 }
3365 let newFile;
3366 if (options.destination instanceof File) {
3367 newFile = options.destination;
3368 }
3369 else if (options.destination !== null &&
3370 typeof options.destination === 'string') {
3371 // Use the string as the name of the file.
3372 newFile = this.file(options.destination, {
3373 encryptionKey: options.encryptionKey,
3374 kmsKeyName: options.kmsKeyName,
3375 preconditionOpts: this.instancePreconditionOpts,
3376 });
3377 }
3378 else {
3379 // Resort to using the name of the incoming file.
3380 const destination = path.basename(pathString);
3381 newFile = this.file(destination, {
3382 encryptionKey: options.encryptionKey,
3383 kmsKeyName: options.kmsKeyName,
3384 preconditionOpts: this.instancePreconditionOpts,
3385 });
3386 }
3387 upload(maxRetries);
3388 }
3389 /**
3390 * @private
3391 *
3392 * @typedef {object} MakeAllFilesPublicPrivateOptions
3393 * @property {boolean} [force] Suppress errors until all files have been
3394 * processed.
3395 * @property {boolean} [private] Make files private.
3396 * @property {boolean} [public] Make files public.
3397 * @property {string} [userProject] The ID of the project which will be
3398 * billed for the request.
3399 */
3400 /**
3401 * @private
3402 *
3403 * @callback SetBucketMetadataCallback
3404 * @param {?Error} err Request error, if any.
3405 * @param {File[]} files Files that were updated.
3406 */
3407 /**
3408 * @typedef {array} MakeAllFilesPublicPrivateResponse
3409 * @property {File[]} 0 List of files affected.
3410 */
3411 /**
3412 * Iterate over all of a bucket's files, calling `file.makePublic()` (public)
3413 * or `file.makePrivate()` (private) on each.
3414 *
3415 * Operations are performed in parallel, up to 10 at once. The first error
3416 * breaks the loop, and will execute the provided callback with it. Specify
3417 * `{ force: true }` to suppress the errors.
3418 *
3419 * @private
3420 *
3421 * @param {MakeAllFilesPublicPrivateOptions} [options] Configuration options.
3422 * @param {boolean} [options.force] Suppress errors until all files have been
3423 * processed.
3424 * @param {boolean} [options.private] Make files private.
3425 * @param {boolean} [options.public] Make files public.
3426 * @param {string} [options.userProject] The ID of the project which will be
3427 * billed for the request.
3428
3429 * @param {MakeAllFilesPublicPrivateCallback} callback Callback function.
3430 *
3431 * @return {Promise<MakeAllFilesPublicPrivateResponse>}
3432 */
3433 makeAllFilesPublicPrivate_(optionsOrCallback, callback) {
3434 const MAX_PARALLEL_LIMIT = 10;
3435 const errors = [];
3436 const updatedFiles = [];
3437 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
3438 callback =
3439 typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
3440 const processFile = async (file) => {
3441 try {
3442 await (options.public ? file.makePublic() : file.makePrivate(options));
3443 updatedFiles.push(file);
3444 }
3445 catch (e) {
3446 if (!options.force) {
3447 throw e;
3448 }
3449 errors.push(e);
3450 }
3451 };
3452 this.getFiles(options)
3453 .then(([files]) => {
3454 const limit = pLimit(MAX_PARALLEL_LIMIT);
3455 const promises = files.map(file => {
3456 return limit(() => processFile(file));
3457 });
3458 return Promise.all(promises);
3459 })
3460 .then(() => callback(errors.length > 0 ? errors : null, updatedFiles), err => callback(err, updatedFiles));
3461 }
3462 getId() {
3463 return this.id;
3464 }
3465 disableAutoRetryConditionallyIdempotent_(
3466 // eslint-disable-next-line @typescript-eslint/no-explicit-any
3467 coreOpts,
3468 // eslint-disable-next-line @typescript-eslint/no-explicit-any
3469 methodType, localPreconditionOptions) {
3470 var _a, _b;
3471 if (typeof coreOpts === 'object' &&
3472 ((_b = (_a = coreOpts === null || coreOpts === void 0 ? void 0 : coreOpts.reqOpts) === null || _a === void 0 ? void 0 : _a.qs) === null || _b === void 0 ? void 0 : _b.ifMetagenerationMatch) === undefined &&
3473 (localPreconditionOptions === null || localPreconditionOptions === void 0 ? void 0 : localPreconditionOptions.ifMetagenerationMatch) === undefined &&
3474 (methodType === AvailableServiceObjectMethods.setMetadata ||
3475 methodType === AvailableServiceObjectMethods.delete) &&
3476 this.storage.retryOptions.idempotencyStrategy ===
3477 IdempotencyStrategy.RetryConditional) {
3478 this.storage.retryOptions.autoRetry = false;
3479 }
3480 else if (this.storage.retryOptions.idempotencyStrategy ===
3481 IdempotencyStrategy.RetryNever) {
3482 this.storage.retryOptions.autoRetry = false;
3483 }
3484 }
3485}
3486/*! Developer Documentation
3487 *
3488 * These methods can be auto-paginated.
3489 */
3490paginator.extend(Bucket, 'getFiles');
3491/*! Developer Documentation
3492 *
3493 * All async methods (except for streams) will return a Promise in the event
3494 * that a callback is omitted.
3495 */
3496promisifyAll(Bucket, {
3497 exclude: ['cloudStorageURI', 'request', 'file', 'notification'],
3498});
3499/**
3500 * Reference to the {@link Bucket} class.
3501 * @name module:@google-cloud/storage.Bucket
3502 * @see Bucket
3503 */
3504export { Bucket };