UNPKG

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