UNPKG

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