UNPKG

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