UNPKG

46.6 kBJavaScriptView Raw
1"use strict";
2// Copyright 2019 Google LLC
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15Object.defineProperty(exports, "__esModule", { value: true });
16exports.Storage = exports.RETRYABLE_ERR_FN_DEFAULT = exports.MAX_RETRY_DELAY_DEFAULT = exports.TOTAL_TIMEOUT_DEFAULT = exports.RETRY_DELAY_MULTIPLIER_DEFAULT = exports.MAX_RETRY_DEFAULT = exports.AUTO_RETRY_DEFAULT = exports.PROTOCOL_REGEX = exports.StorageExceptionMessages = exports.ExceptionMessages = exports.IdempotencyStrategy = void 0;
17const index_js_1 = require("./nodejs-common/index.js");
18const paginator_1 = require("@google-cloud/paginator");
19const promisify_1 = require("@google-cloud/promisify");
20const stream_1 = require("stream");
21const bucket_js_1 = require("./bucket.js");
22const channel_js_1 = require("./channel.js");
23const file_js_1 = require("./file.js");
24const util_js_1 = require("./util.js");
25// eslint-disable-next-line @typescript-eslint/ban-ts-comment
26// @ts-ignore
27const package_json_helper_cjs_1 = require("./package-json-helper.cjs");
28const hmacKey_js_1 = require("./hmacKey.js");
29const crc32c_js_1 = require("./crc32c.js");
30const google_auth_library_1 = require("google-auth-library");
31var IdempotencyStrategy;
32(function (IdempotencyStrategy) {
33 IdempotencyStrategy[IdempotencyStrategy["RetryAlways"] = 0] = "RetryAlways";
34 IdempotencyStrategy[IdempotencyStrategy["RetryConditional"] = 1] = "RetryConditional";
35 IdempotencyStrategy[IdempotencyStrategy["RetryNever"] = 2] = "RetryNever";
36})(IdempotencyStrategy || (exports.IdempotencyStrategy = IdempotencyStrategy = {}));
37var ExceptionMessages;
38(function (ExceptionMessages) {
39 ExceptionMessages["EXPIRATION_DATE_INVALID"] = "The expiration date provided was invalid.";
40 ExceptionMessages["EXPIRATION_DATE_PAST"] = "An expiration date cannot be in the past.";
41})(ExceptionMessages || (exports.ExceptionMessages = ExceptionMessages = {}));
42var StorageExceptionMessages;
43(function (StorageExceptionMessages) {
44 StorageExceptionMessages["BUCKET_NAME_REQUIRED"] = "A bucket name is needed to use Cloud Storage.";
45 StorageExceptionMessages["BUCKET_NAME_REQUIRED_CREATE"] = "A name is required to create a bucket.";
46 StorageExceptionMessages["HMAC_SERVICE_ACCOUNT"] = "The first argument must be a service account email to create an HMAC key.";
47 StorageExceptionMessages["HMAC_ACCESS_ID"] = "An access ID is needed to create an HmacKey object.";
48})(StorageExceptionMessages || (exports.StorageExceptionMessages = StorageExceptionMessages = {}));
49exports.PROTOCOL_REGEX = /^(\w*):\/\//;
50/**
51 * Default behavior: Automatically retry retriable server errors.
52 *
53 * @const {boolean}
54 */
55exports.AUTO_RETRY_DEFAULT = true;
56/**
57 * Default behavior: Only attempt to retry retriable errors 3 times.
58 *
59 * @const {number}
60 */
61exports.MAX_RETRY_DEFAULT = 3;
62/**
63 * Default behavior: Wait twice as long as previous retry before retrying.
64 *
65 * @const {number}
66 */
67exports.RETRY_DELAY_MULTIPLIER_DEFAULT = 2;
68/**
69 * Default behavior: If the operation doesn't succeed after 600 seconds,
70 * stop retrying.
71 *
72 * @const {number}
73 */
74exports.TOTAL_TIMEOUT_DEFAULT = 600;
75/**
76 * Default behavior: Wait no more than 64 seconds between retries.
77 *
78 * @const {number}
79 */
80exports.MAX_RETRY_DELAY_DEFAULT = 64;
81/**
82 * Default behavior: Retry conditionally idempotent operations if correct preconditions are set.
83 *
84 * @const {enum}
85 * @private
86 */
87const IDEMPOTENCY_STRATEGY_DEFAULT = IdempotencyStrategy.RetryConditional;
88/**
89 * Returns true if the API request should be retried, given the error that was
90 * given the first time the request was attempted.
91 * @const
92 * @param {error} err - The API error to check if it is appropriate to retry.
93 * @return {boolean} True if the API request should be retried, false otherwise.
94 */
95const RETRYABLE_ERR_FN_DEFAULT = function (err) {
96 var _a;
97 const isConnectionProblem = (reason) => {
98 return (reason.includes('eai_again') || // DNS lookup error
99 reason === 'econnreset' ||
100 reason === 'unexpected connection closure' ||
101 reason === 'epipe' ||
102 reason === 'socket connection timeout');
103 };
104 if (err) {
105 if ([408, 429, 500, 502, 503, 504].indexOf(err.code) !== -1) {
106 return true;
107 }
108 if (typeof err.code === 'string') {
109 if (['408', '429', '500', '502', '503', '504'].indexOf(err.code) !== -1) {
110 return true;
111 }
112 const reason = err.code.toLowerCase();
113 if (isConnectionProblem(reason)) {
114 return true;
115 }
116 }
117 if (err.errors) {
118 for (const e of err.errors) {
119 const reason = (_a = e === null || e === void 0 ? void 0 : e.reason) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase();
120 if (reason && isConnectionProblem(reason)) {
121 return true;
122 }
123 }
124 }
125 }
126 return false;
127};
128exports.RETRYABLE_ERR_FN_DEFAULT = RETRYABLE_ERR_FN_DEFAULT;
129/*! Developer Documentation
130 *
131 * Invoke this method to create a new Storage object bound with pre-determined
132 * configuration options. For each object that can be created (e.g., a bucket),
133 * there is an equivalent static and instance method. While they are classes,
134 * they can be instantiated without use of the `new` keyword.
135 */
136/**
137 * Cloud Storage uses access control lists (ACLs) to manage object and
138 * bucket access. ACLs are the mechanism you use to share objects with other
139 * users and allow other users to access your buckets and objects.
140 *
141 * This object provides constants to refer to the three permission levels that
142 * can be granted to an entity:
143 *
144 * - `gcs.acl.OWNER_ROLE` - ("OWNER")
145 * - `gcs.acl.READER_ROLE` - ("READER")
146 * - `gcs.acl.WRITER_ROLE` - ("WRITER")
147 *
148 * See {@link https://cloud.google.com/storage/docs/access-control/lists| About Access Control Lists}
149 *
150 * @name Storage#acl
151 * @type {object}
152 * @property {string} OWNER_ROLE
153 * @property {string} READER_ROLE
154 * @property {string} WRITER_ROLE
155 *
156 * @example
157 * ```
158 * const {Storage} = require('@google-cloud/storage');
159 * const storage = new Storage();
160 * const albums = storage.bucket('albums');
161 *
162 * //-
163 * // Make all of the files currently in a bucket publicly readable.
164 * //-
165 * const options = {
166 * entity: 'allUsers',
167 * role: storage.acl.READER_ROLE
168 * };
169 *
170 * albums.acl.add(options, function(err, aclObject) {});
171 *
172 * //-
173 * // Make any new objects added to a bucket publicly readable.
174 * //-
175 * albums.acl.default.add(options, function(err, aclObject) {});
176 *
177 * //-
178 * // Grant a user ownership permissions to a bucket.
179 * //-
180 * albums.acl.add({
181 * entity: 'user-useremail@example.com',
182 * role: storage.acl.OWNER_ROLE
183 * }, function(err, aclObject) {});
184 *
185 * //-
186 * // If the callback is omitted, we'll return a Promise.
187 * //-
188 * albums.acl.add(options).then(function(data) {
189 * const aclObject = data[0];
190 * const apiResponse = data[1];
191 * });
192 * ```
193 */
194/**
195 * Get {@link Bucket} objects for all of the buckets in your project as
196 * a readable object stream.
197 *
198 * @method Storage#getBucketsStream
199 * @param {GetBucketsRequest} [query] Query object for listing buckets.
200 * @returns {ReadableStream} A readable stream that emits {@link Bucket}
201 * instances.
202 *
203 * @example
204 * ```
205 * storage.getBucketsStream()
206 * .on('error', console.error)
207 * .on('data', function(bucket) {
208 * // bucket is a Bucket object.
209 * })
210 * .on('end', function() {
211 * // All buckets retrieved.
212 * });
213 *
214 * //-
215 * // If you anticipate many results, you can end a stream early to prevent
216 * // unnecessary processing and API requests.
217 * //-
218 * storage.getBucketsStream()
219 * .on('data', function(bucket) {
220 * this.end();
221 * });
222 * ```
223 */
224/**
225 * Get {@link HmacKey} objects for all of the HMAC keys in the project in a
226 * readable object stream.
227 *
228 * @method Storage#getHmacKeysStream
229 * @param {GetHmacKeysOptions} [options] Configuration options.
230 * @returns {ReadableStream} A readable stream that emits {@link HmacKey}
231 * instances.
232 *
233 * @example
234 * ```
235 * storage.getHmacKeysStream()
236 * .on('error', console.error)
237 * .on('data', function(hmacKey) {
238 * // hmacKey is an HmacKey object.
239 * })
240 * .on('end', function() {
241 * // All HmacKey retrieved.
242 * });
243 *
244 * //-
245 * // If you anticipate many results, you can end a stream early to prevent
246 * // unnecessary processing and API requests.
247 * //-
248 * storage.getHmacKeysStream()
249 * .on('data', function(bucket) {
250 * this.end();
251 * });
252 * ```
253 */
254/**
255 * <h4>ACLs</h4>
256 * Cloud Storage uses access control lists (ACLs) to manage object and
257 * bucket access. ACLs are the mechanism you use to share files with other users
258 * and allow other users to access your buckets and files.
259 *
260 * To learn more about ACLs, read this overview on
261 * {@link https://cloud.google.com/storage/docs/access-control| Access Control}.
262 *
263 * See {@link https://cloud.google.com/storage/docs/overview| Cloud Storage overview}
264 * See {@link https://cloud.google.com/storage/docs/access-control| Access Control}
265 *
266 * @class
267 */
268class Storage extends index_js_1.Service {
269 getBucketsStream() {
270 // placeholder body, overwritten in constructor
271 return new stream_1.Readable();
272 }
273 getHmacKeysStream() {
274 // placeholder body, overwritten in constructor
275 return new stream_1.Readable();
276 }
277 /**
278 * @callback Crc32cGeneratorToStringCallback
279 * A method returning the CRC32C as a base64-encoded string.
280 *
281 * @returns {string}
282 *
283 * @example
284 * Hashing the string 'data' should return 'rth90Q=='
285 *
286 * ```js
287 * const buffer = Buffer.from('data');
288 * crc32c.update(buffer);
289 * crc32c.toString(); // 'rth90Q=='
290 * ```
291 **/
292 /**
293 * @callback Crc32cGeneratorValidateCallback
294 * A method validating a base64-encoded CRC32C string.
295 *
296 * @param {string} [value] base64-encoded CRC32C string to validate
297 * @returns {boolean}
298 *
299 * @example
300 * Should return `true` if the value matches, `false` otherwise
301 *
302 * ```js
303 * const buffer = Buffer.from('data');
304 * crc32c.update(buffer);
305 * crc32c.validate('DkjKuA=='); // false
306 * crc32c.validate('rth90Q=='); // true
307 * ```
308 **/
309 /**
310 * @callback Crc32cGeneratorUpdateCallback
311 * A method for passing `Buffer`s for CRC32C generation.
312 *
313 * @param {Buffer} [data] data to update CRC32C value with
314 * @returns {undefined}
315 *
316 * @example
317 * Hashing buffers from 'some ' and 'text\n'
318 *
319 * ```js
320 * const buffer1 = Buffer.from('some ');
321 * crc32c.update(buffer1);
322 *
323 * const buffer2 = Buffer.from('text\n');
324 * crc32c.update(buffer2);
325 *
326 * crc32c.toString(); // 'DkjKuA=='
327 * ```
328 **/
329 /**
330 * @typedef {object} CRC32CValidator
331 * @property {Crc32cGeneratorToStringCallback}
332 * @property {Crc32cGeneratorValidateCallback}
333 * @property {Crc32cGeneratorUpdateCallback}
334 */
335 /**
336 * @callback Crc32cGeneratorCallback
337 * @returns {CRC32CValidator}
338 */
339 /**
340 * @typedef {object} StorageOptions
341 * @property {string} [projectId] The project ID from the Google Developer's
342 * Console, e.g. 'grape-spaceship-123'. We will also check the environment
343 * variable `GCLOUD_PROJECT` for your project ID. If your app is running
344 * in an environment which supports {@link
345 * https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application
346 * Application Default Credentials}, your project ID will be detected
347 * automatically.
348 * @property {string} [keyFilename] Full path to the a .json, .pem, or .p12 key
349 * downloaded from the Google Developers Console. If you provide a path to
350 * a JSON file, the `projectId` option above is not necessary. NOTE: .pem and
351 * .p12 require you to specify the `email` option as well.
352 * @property {string} [email] Account email address. Required when using a .pem
353 * or .p12 keyFilename.
354 * @property {object} [credentials] Credentials object.
355 * @property {string} [credentials.client_email]
356 * @property {string} [credentials.private_key]
357 * @property {object} [retryOptions] Options for customizing retries. Retriable server errors
358 * will be retried with exponential delay between them dictated by the formula
359 * max(maxRetryDelay, retryDelayMultiplier*retryNumber) until maxRetries or totalTimeout
360 * has been reached. Retries will only happen if autoRetry is set to true.
361 * @property {boolean} [retryOptions.autoRetry=true] Automatically retry requests if the
362 * response is related to rate limits or certain intermittent server
363 * errors. We will exponentially backoff subsequent requests by default.
364 * @property {number} [retryOptions.retryDelayMultiplier = 2] the multiplier by which to
365 * increase the delay time between the completion of failed requests, and the
366 * initiation of the subsequent retrying request.
367 * @property {number} [retryOptions.totalTimeout = 600] The total time, starting from
368 * when the initial request is sent, after which an error will
369 * be returned, regardless of the retrying attempts made meanwhile.
370 * @property {number} [retryOptions.maxRetryDelay = 64] The maximum delay time between requests.
371 * When this value is reached, ``retryDelayMultiplier`` will no longer be used to
372 * increase delay time.
373 * @property {number} [retryOptions.maxRetries=3] Maximum number of automatic retries
374 * attempted before returning the error.
375 * @property {function} [retryOptions.retryableErrorFn] Function that returns true if a given
376 * error should be retried and false otherwise.
377 * @property {enum} [retryOptions.idempotencyStrategy=IdempotencyStrategy.RetryConditional] Enumeration
378 * controls how conditionally idempotent operations are retried. Possible values are: RetryAlways -
379 * will respect other retry settings and attempt to retry conditionally idempotent operations. RetryConditional -
380 * will retry conditionally idempotent operations if the correct preconditions are set. RetryNever - never
381 * retry a conditionally idempotent operation.
382 * @property {string} [userAgent] The value to be prepended to the User-Agent
383 * header in API requests.
384 * @property {object} [authClient] `AuthClient` or `GoogleAuth` client to reuse instead of creating a new one.
385 * @property {number} [timeout] The amount of time in milliseconds to wait per http request before timing out.
386 * @property {object[]} [interceptors_] Array of custom request interceptors to be returned in the order they were assigned.
387 * @property {string} [apiEndpoint = storage.google.com] The API endpoint of the service used to make requests.
388 * @property {boolean} [useAuthWithCustomEndpoint = false] Controls whether or not to use authentication when using a custom endpoint.
389 * @property {Crc32cGeneratorCallback} [callback] A function that generates a CRC32C Validator. Defaults to {@link CRC32C}
390 */
391 /**
392 * Constructs the Storage client.
393 *
394 * @example
395 * Create a client that uses Application Default Credentials
396 * (ADC)
397 * ```
398 * const {Storage} = require('@google-cloud/storage');
399 * const storage = new Storage();
400 * ```
401 *
402 * @example
403 * Create a client with explicit credentials
404 * ```
405 * const storage = new Storage({
406 * projectId: 'your-project-id',
407 * keyFilename: '/path/to/keyfile.json'
408 * });
409 * ```
410 *
411 * @example
412 * Create a client with credentials passed
413 * by value as a JavaScript object
414 * ```
415 * const storage = new Storage({
416 * projectId: 'your-project-id',
417 * credentials: {
418 * type: 'service_account',
419 * project_id: 'xxxxxxx',
420 * private_key_id: 'xxxx',
421 * private_key:'-----BEGIN PRIVATE KEY-----xxxxxxx\n-----END PRIVATE KEY-----\n',
422 * client_email: 'xxxx',
423 * client_id: 'xxx',
424 * auth_uri: 'https://accounts.google.com/o/oauth2/auth',
425 * token_uri: 'https://oauth2.googleapis.com/token',
426 * auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs',
427 * client_x509_cert_url: 'xxx',
428 * }
429 * });
430 * ```
431 *
432 * @example
433 * Create a client with credentials passed
434 * by loading a JSON file directly from disk
435 * ```
436 * const storage = new Storage({
437 * projectId: 'your-project-id',
438 * credentials: require('/path/to-keyfile.json')
439 * });
440 * ```
441 *
442 * @example
443 * Create a client with an `AuthClient` (e.g. `DownscopedClient`)
444 * ```
445 * const {DownscopedClient} = require('google-auth-library');
446 * const authClient = new DownscopedClient({...});
447 *
448 * const storage = new Storage({authClient});
449 * ```
450 *
451 * Additional samples:
452 * - https://github.com/googleapis/google-auth-library-nodejs#sample-usage-1
453 * - https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/downscopedclient.js
454 *
455 * @param {StorageOptions} [options] Configuration options.
456 */
457 constructor(options = {}) {
458 var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
459 const universe = options.universeDomain || google_auth_library_1.DEFAULT_UNIVERSE;
460 let apiEndpoint = `https://storage.${universe}`;
461 let customEndpoint = false;
462 // Note: EMULATOR_HOST is an experimental configuration variable. Use apiEndpoint instead.
463 const EMULATOR_HOST = process.env.STORAGE_EMULATOR_HOST;
464 if (typeof EMULATOR_HOST === 'string') {
465 apiEndpoint = Storage.sanitizeEndpoint(EMULATOR_HOST);
466 customEndpoint = true;
467 }
468 if (options.apiEndpoint && options.apiEndpoint !== apiEndpoint) {
469 apiEndpoint = Storage.sanitizeEndpoint(options.apiEndpoint);
470 customEndpoint = true;
471 }
472 options = Object.assign({}, options, { apiEndpoint });
473 // Note: EMULATOR_HOST is an experimental configuration variable. Use apiEndpoint instead.
474 const baseUrl = EMULATOR_HOST || `${options.apiEndpoint}/storage/v1`;
475 const config = {
476 apiEndpoint: options.apiEndpoint,
477 retryOptions: {
478 autoRetry: ((_a = options.retryOptions) === null || _a === void 0 ? void 0 : _a.autoRetry) !== undefined
479 ? (_b = options.retryOptions) === null || _b === void 0 ? void 0 : _b.autoRetry
480 : exports.AUTO_RETRY_DEFAULT,
481 maxRetries: ((_c = options.retryOptions) === null || _c === void 0 ? void 0 : _c.maxRetries)
482 ? (_d = options.retryOptions) === null || _d === void 0 ? void 0 : _d.maxRetries
483 : exports.MAX_RETRY_DEFAULT,
484 retryDelayMultiplier: ((_e = options.retryOptions) === null || _e === void 0 ? void 0 : _e.retryDelayMultiplier)
485 ? (_f = options.retryOptions) === null || _f === void 0 ? void 0 : _f.retryDelayMultiplier
486 : exports.RETRY_DELAY_MULTIPLIER_DEFAULT,
487 totalTimeout: ((_g = options.retryOptions) === null || _g === void 0 ? void 0 : _g.totalTimeout)
488 ? (_h = options.retryOptions) === null || _h === void 0 ? void 0 : _h.totalTimeout
489 : exports.TOTAL_TIMEOUT_DEFAULT,
490 maxRetryDelay: ((_j = options.retryOptions) === null || _j === void 0 ? void 0 : _j.maxRetryDelay)
491 ? (_k = options.retryOptions) === null || _k === void 0 ? void 0 : _k.maxRetryDelay
492 : exports.MAX_RETRY_DELAY_DEFAULT,
493 retryableErrorFn: ((_l = options.retryOptions) === null || _l === void 0 ? void 0 : _l.retryableErrorFn)
494 ? (_m = options.retryOptions) === null || _m === void 0 ? void 0 : _m.retryableErrorFn
495 : exports.RETRYABLE_ERR_FN_DEFAULT,
496 idempotencyStrategy: ((_o = options.retryOptions) === null || _o === void 0 ? void 0 : _o.idempotencyStrategy) !== undefined
497 ? (_p = options.retryOptions) === null || _p === void 0 ? void 0 : _p.idempotencyStrategy
498 : IDEMPOTENCY_STRATEGY_DEFAULT,
499 },
500 baseUrl,
501 customEndpoint,
502 useAuthWithCustomEndpoint: options === null || options === void 0 ? void 0 : options.useAuthWithCustomEndpoint,
503 projectIdRequired: false,
504 scopes: [
505 'https://www.googleapis.com/auth/iam',
506 'https://www.googleapis.com/auth/cloud-platform',
507 'https://www.googleapis.com/auth/devstorage.full_control',
508 ],
509 packageJson: (0, package_json_helper_cjs_1.getPackageJSON)(),
510 };
511 super(config, options);
512 /**
513 * Reference to {@link Storage.acl}.
514 *
515 * @name Storage#acl
516 * @see Storage.acl
517 */
518 this.acl = Storage.acl;
519 this.crc32cGenerator =
520 options.crc32cGenerator || crc32c_js_1.CRC32C_DEFAULT_VALIDATOR_GENERATOR;
521 this.retryOptions = config.retryOptions;
522 this.getBucketsStream = paginator_1.paginator.streamify('getBuckets');
523 this.getHmacKeysStream = paginator_1.paginator.streamify('getHmacKeys');
524 }
525 static sanitizeEndpoint(url) {
526 if (!exports.PROTOCOL_REGEX.test(url)) {
527 url = `https://${url}`;
528 }
529 return url.replace(/\/+$/, ''); // Remove trailing slashes
530 }
531 /**
532 * Get a reference to a Cloud Storage bucket.
533 *
534 * @param {string} name Name of the bucket.
535 * @param {object} [options] Configuration object.
536 * @param {string} [options.kmsKeyName] A Cloud KMS key that will be used to
537 * encrypt objects inserted into this bucket, if no encryption method is
538 * specified.
539 * @param {string} [options.userProject] User project to be billed for all
540 * requests made from this Bucket object.
541 * @returns {Bucket}
542 * @see Bucket
543 *
544 * @example
545 * ```
546 * const {Storage} = require('@google-cloud/storage');
547 * const storage = new Storage();
548 * const albums = storage.bucket('albums');
549 * const photos = storage.bucket('photos');
550 * ```
551 */
552 bucket(name, options) {
553 if (!name) {
554 throw new Error(StorageExceptionMessages.BUCKET_NAME_REQUIRED);
555 }
556 return new bucket_js_1.Bucket(this, name, options);
557 }
558 /**
559 * Reference a channel to receive notifications about changes to your bucket.
560 *
561 * @param {string} id The ID of the channel.
562 * @param {string} resourceId The resource ID of the channel.
563 * @returns {Channel}
564 * @see Channel
565 *
566 * @example
567 * ```
568 * const {Storage} = require('@google-cloud/storage');
569 * const storage = new Storage();
570 * const channel = storage.channel('id', 'resource-id');
571 * ```
572 */
573 channel(id, resourceId) {
574 return new channel_js_1.Channel(this, id, resourceId);
575 }
576 /**
577 * @typedef {array} CreateBucketResponse
578 * @property {Bucket} 0 The new {@link Bucket}.
579 * @property {object} 1 The full API response.
580 */
581 /**
582 * @callback CreateBucketCallback
583 * @param {?Error} err Request error, if any.
584 * @param {Bucket} bucket The new {@link Bucket}.
585 * @param {object} apiResponse The full API response.
586 */
587 /**
588 * Metadata to set for the bucket.
589 *
590 * @typedef {object} CreateBucketRequest
591 * @property {boolean} [archive=false] Specify the storage class as Archive.
592 * @property {object} [autoclass.enabled=false] Specify whether Autoclass is
593 * enabled for the bucket.
594 * @property {object} [autoclass.terminalStorageClass='NEARLINE'] The storage class that objects in an Autoclass bucket eventually transition to if
595 * they are not read for a certain length of time. Valid values are NEARLINE and ARCHIVE.
596 * @property {boolean} [coldline=false] Specify the storage class as Coldline.
597 * @property {Cors[]} [cors=[]] Specify the CORS configuration to use.
598 * @property {CustomPlacementConfig} [customPlacementConfig={}] Specify the bucket's regions for dual-region buckets.
599 * For more information, see {@link https://cloud.google.com/storage/docs/locations| Bucket Locations}.
600 * @property {boolean} [dra=false] Specify the storage class as Durable Reduced
601 * Availability.
602 * @property {boolean} [enableObjectRetention=false] Specifiy whether or not object retention should be enabled on this bucket.
603 * @property {object} [hierarchicalNamespace.enabled=false] Specify whether or not to enable hierarchical namespace on this bucket.
604 * @property {string} [location] Specify the bucket's location. If specifying
605 * a dual-region, the `customPlacementConfig` property should be set in conjunction.
606 * For more information, see {@link https://cloud.google.com/storage/docs/locations| Bucket Locations}.
607 * @property {boolean} [multiRegional=false] Specify the storage class as
608 * Multi-Regional.
609 * @property {boolean} [nearline=false] Specify the storage class as Nearline.
610 * @property {boolean} [regional=false] Specify the storage class as Regional.
611 * @property {boolean} [requesterPays=false] Force the use of the User Project metadata field to assign operational
612 * costs when an operation is made on a Bucket and its objects.
613 * @property {string} [rpo] For dual-region buckets, controls whether turbo
614 * replication is enabled (`ASYNC_TURBO`) or disabled (`DEFAULT`).
615 * @property {boolean} [standard=true] Specify the storage class as Standard.
616 * @property {string} [storageClass] The new storage class. (`standard`,
617 * `nearline`, `coldline`, or `archive`).
618 * **Note:** The storage classes `multi_regional`, `regional`, and
619 * `durable_reduced_availability` are now legacy and will be deprecated in
620 * the future.
621 * @property {Versioning} [versioning=undefined] Specify the versioning status.
622 * @property {string} [userProject] The ID of the project which will be billed
623 * for the request.
624 */
625 /**
626 * Create a bucket.
627 *
628 * Cloud Storage uses a flat namespace, so you can't create a bucket with
629 * a name that is already in use. For more information, see
630 * {@link https://cloud.google.com/storage/docs/bucketnaming.html#requirements| Bucket Naming Guidelines}.
631 *
632 * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/insert| Buckets: insert API Documentation}
633 * See {@link https://cloud.google.com/storage/docs/storage-classes| Storage Classes}
634 *
635 * @param {string} name Name of the bucket to create.
636 * @param {CreateBucketRequest} [metadata] Metadata to set for the bucket.
637 * @param {CreateBucketCallback} [callback] Callback function.
638 * @returns {Promise<CreateBucketResponse>}
639 * @throws {Error} If a name is not provided.
640 * @see Bucket#create
641 *
642 * @example
643 * ```
644 * const {Storage} = require('@google-cloud/storage');
645 * const storage = new Storage();
646 * const callback = function(err, bucket, apiResponse) {
647 * // `bucket` is a Bucket object.
648 * };
649 *
650 * storage.createBucket('new-bucket', callback);
651 *
652 * //-
653 * // Create a bucket in a specific location and region. <em>See the <a
654 * // href="https://cloud.google.com/storage/docs/json_api/v1/buckets/insert">
655 * // Official JSON API docs</a> for complete details on the `location`
656 * option.
657 * // </em>
658 * //-
659 * const metadata = {
660 * location: 'US-CENTRAL1',
661 * regional: true
662 * };
663 *
664 * storage.createBucket('new-bucket', metadata, callback);
665 *
666 * //-
667 * // Create a bucket with a retention policy of 6 months.
668 * //-
669 * const metadata = {
670 * retentionPolicy: {
671 * retentionPeriod: 15780000 // 6 months in seconds.
672 * }
673 * };
674 *
675 * storage.createBucket('new-bucket', metadata, callback);
676 *
677 * //-
678 * // Enable versioning on a new bucket.
679 * //-
680 * const metadata = {
681 * versioning: {
682 * enabled: true
683 * }
684 * };
685 *
686 * storage.createBucket('new-bucket', metadata, callback);
687 *
688 * //-
689 * // If the callback is omitted, we'll return a Promise.
690 * //-
691 * storage.createBucket('new-bucket').then(function(data) {
692 * const bucket = data[0];
693 * const apiResponse = data[1];
694 * });
695 *
696 * ```
697 * @example <caption>include:samples/buckets.js</caption>
698 * region_tag:storage_create_bucket
699 * Another example:
700 */
701 createBucket(name, metadataOrCallback, callback) {
702 if (!name) {
703 throw new Error(StorageExceptionMessages.BUCKET_NAME_REQUIRED_CREATE);
704 }
705 let metadata;
706 if (!callback) {
707 callback = metadataOrCallback;
708 metadata = {};
709 }
710 else {
711 metadata = metadataOrCallback;
712 }
713 const body = {
714 ...metadata,
715 name,
716 };
717 const storageClasses = {
718 archive: 'ARCHIVE',
719 coldline: 'COLDLINE',
720 dra: 'DURABLE_REDUCED_AVAILABILITY',
721 multiRegional: 'MULTI_REGIONAL',
722 nearline: 'NEARLINE',
723 regional: 'REGIONAL',
724 standard: 'STANDARD',
725 };
726 const storageClassKeys = Object.keys(storageClasses);
727 for (const storageClass of storageClassKeys) {
728 if (body[storageClass]) {
729 if (metadata.storageClass && metadata.storageClass !== storageClass) {
730 throw new Error(`Both \`${storageClass}\` and \`storageClass\` were provided.`);
731 }
732 body.storageClass = storageClasses[storageClass];
733 delete body[storageClass];
734 }
735 }
736 if (body.requesterPays) {
737 body.billing = {
738 requesterPays: body.requesterPays,
739 };
740 delete body.requesterPays;
741 }
742 const query = {
743 project: this.projectId,
744 };
745 if (body.userProject) {
746 query.userProject = body.userProject;
747 delete body.userProject;
748 }
749 if (body.enableObjectRetention) {
750 query.enableObjectRetention = body.enableObjectRetention;
751 delete body.enableObjectRetention;
752 }
753 if (body.predefinedAcl) {
754 query.predefinedAcl = body.predefinedAcl;
755 delete body.predefinedAcl;
756 }
757 if (body.predefinedDefaultObjectAcl) {
758 query.predefinedDefaultObjectAcl = body.predefinedDefaultObjectAcl;
759 delete body.predefinedDefaultObjectAcl;
760 }
761 if (body.projection) {
762 query.projection = body.projection;
763 delete body.projection;
764 }
765 this.request({
766 method: 'POST',
767 uri: '/b',
768 qs: query,
769 json: body,
770 }, (err, resp) => {
771 if (err) {
772 callback(err, null, resp);
773 return;
774 }
775 const bucket = this.bucket(name);
776 bucket.metadata = resp;
777 callback(null, bucket, resp);
778 });
779 }
780 /**
781 * @typedef {object} CreateHmacKeyOptions
782 * @property {string} [projectId] The project ID of the project that owns
783 * the service account of the requested HMAC key. If not provided,
784 * the project ID used to instantiate the Storage client will be used.
785 * @property {string} [userProject] This parameter is currently ignored.
786 */
787 /**
788 * @typedef {object} HmacKeyMetadata
789 * @property {string} accessId The access id identifies which HMAC key was
790 * used to sign a request when authenticating with HMAC.
791 * @property {string} etag Used to perform a read-modify-write of the key.
792 * @property {string} id The resource name of the HMAC key.
793 * @property {string} projectId The project ID.
794 * @property {string} serviceAccountEmail The service account's email this
795 * HMAC key is created for.
796 * @property {string} state The state of this HMAC key. One of "ACTIVE",
797 * "INACTIVE" or "DELETED".
798 * @property {string} timeCreated The creation time of the HMAC key in
799 * RFC 3339 format.
800 * @property {string} [updated] The time this HMAC key was last updated in
801 * RFC 3339 format.
802 */
803 /**
804 * @typedef {array} CreateHmacKeyResponse
805 * @property {HmacKey} 0 The HmacKey instance created from API response.
806 * @property {string} 1 The HMAC key's secret used to access the XML API.
807 * @property {object} 3 The raw API response.
808 */
809 /**
810 * @callback CreateHmacKeyCallback Callback function.
811 * @param {?Error} err Request error, if any.
812 * @param {HmacKey} hmacKey The HmacKey instance created from API response.
813 * @param {string} secret The HMAC key's secret used to access the XML API.
814 * @param {object} apiResponse The raw API response.
815 */
816 /**
817 * Create an HMAC key associated with an service account to authenticate
818 * requests to the Cloud Storage XML API.
819 *
820 * See {@link https://cloud.google.com/storage/docs/authentication/hmackeys| HMAC keys documentation}
821 *
822 * @param {string} serviceAccountEmail The service account's email address
823 * with which the HMAC key is created for.
824 * @param {CreateHmacKeyCallback} [callback] Callback function.
825 * @return {Promise<CreateHmacKeyResponse>}
826 *
827 * @example
828 * ```
829 * const {Storage} = require('google-cloud/storage');
830 * const storage = new Storage();
831 *
832 * // Replace with your service account's email address
833 * const serviceAccountEmail =
834 * 'my-service-account@appspot.gserviceaccount.com';
835 *
836 * storage.createHmacKey(serviceAccountEmail, function(err, hmacKey, secret) {
837 * if (!err) {
838 * // Securely store the secret for use with the XML API.
839 * }
840 * });
841 *
842 * //-
843 * // If the callback is omitted, we'll return a Promise.
844 * //-
845 * storage.createHmacKey(serviceAccountEmail)
846 * .then((response) => {
847 * const hmacKey = response[0];
848 * const secret = response[1];
849 * // Securely store the secret for use with the XML API.
850 * });
851 * ```
852 */
853 createHmacKey(serviceAccountEmail, optionsOrCb, cb) {
854 if (typeof serviceAccountEmail !== 'string') {
855 throw new Error(StorageExceptionMessages.HMAC_SERVICE_ACCOUNT);
856 }
857 const { options, callback } = (0, util_js_1.normalize)(optionsOrCb, cb);
858 const query = Object.assign({}, options, { serviceAccountEmail });
859 const projectId = query.projectId || this.projectId;
860 delete query.projectId;
861 this.request({
862 method: 'POST',
863 uri: `/projects/${projectId}/hmacKeys`,
864 qs: query,
865 maxRetries: 0, //explicitly set this value since this is a non-idempotent function
866 }, (err, resp) => {
867 if (err) {
868 callback(err, null, null, resp);
869 return;
870 }
871 const metadata = resp.metadata;
872 const hmacKey = this.hmacKey(metadata.accessId, {
873 projectId: metadata.projectId,
874 });
875 hmacKey.metadata = resp.metadata;
876 callback(null, hmacKey, resp.secret, resp);
877 });
878 }
879 /**
880 * Query object for listing buckets.
881 *
882 * @typedef {object} GetBucketsRequest
883 * @property {boolean} [autoPaginate=true] Have pagination handled
884 * automatically.
885 * @property {number} [maxApiCalls] Maximum number of API calls to make.
886 * @property {number} [maxResults] Maximum number of items plus prefixes to
887 * return per call.
888 * Note: By default will handle pagination automatically
889 * if more than 1 page worth of results are requested per call.
890 * When `autoPaginate` is set to `false` the smaller of `maxResults`
891 * or 1 page of results will be returned per call.
892 * @property {string} [pageToken] A previously-returned page token
893 * representing part of the larger set of results to view.
894 * @property {string} [userProject] The ID of the project which will be billed
895 * for the request.
896 */
897 /**
898 * @typedef {array} GetBucketsResponse
899 * @property {Bucket[]} 0 Array of {@link Bucket} instances.
900 * @property {object} 1 nextQuery A query object to receive more results.
901 * @property {object} 2 The full API response.
902 */
903 /**
904 * @callback GetBucketsCallback
905 * @param {?Error} err Request error, if any.
906 * @param {Bucket[]} buckets Array of {@link Bucket} instances.
907 * @param {object} nextQuery A query object to receive more results.
908 * @param {object} apiResponse The full API response.
909 */
910 /**
911 * Get Bucket objects for all of the buckets in your project.
912 *
913 * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/list| Buckets: list API Documentation}
914 *
915 * @param {GetBucketsRequest} [query] Query object for listing buckets.
916 * @param {GetBucketsCallback} [callback] Callback function.
917 * @returns {Promise<GetBucketsResponse>}
918 *
919 * @example
920 * ```
921 * const {Storage} = require('@google-cloud/storage');
922 * const storage = new Storage();
923 * storage.getBuckets(function(err, buckets) {
924 * if (!err) {
925 * // buckets is an array of Bucket objects.
926 * }
927 * });
928 *
929 * //-
930 * // To control how many API requests are made and page through the results
931 * // manually, set `autoPaginate` to `false`.
932 * //-
933 * const callback = function(err, buckets, nextQuery, apiResponse) {
934 * if (nextQuery) {
935 * // More results exist.
936 * storage.getBuckets(nextQuery, callback);
937 * }
938 *
939 * // The `metadata` property is populated for you with the metadata at the
940 * // time of fetching.
941 * buckets[0].metadata;
942 *
943 * // However, in cases where you are concerned the metadata could have
944 * // changed, use the `getMetadata` method.
945 * buckets[0].getMetadata(function(err, metadata, apiResponse) {});
946 * };
947 *
948 * storage.getBuckets({
949 * autoPaginate: false
950 * }, callback);
951 *
952 * //-
953 * // If the callback is omitted, we'll return a Promise.
954 * //-
955 * storage.getBuckets().then(function(data) {
956 * const buckets = data[0];
957 * });
958 *
959 * ```
960 * @example <caption>include:samples/buckets.js</caption>
961 * region_tag:storage_list_buckets
962 * Another example:
963 */
964 getBuckets(optionsOrCallback, cb) {
965 const { options, callback } = (0, util_js_1.normalize)(optionsOrCallback, cb);
966 options.project = options.project || this.projectId;
967 this.request({
968 uri: '/b',
969 qs: options,
970 }, (err, resp) => {
971 if (err) {
972 callback(err, null, null, resp);
973 return;
974 }
975 const itemsArray = resp.items ? resp.items : [];
976 const buckets = itemsArray.map((bucket) => {
977 const bucketInstance = this.bucket(bucket.id);
978 bucketInstance.metadata = bucket;
979 return bucketInstance;
980 });
981 const nextQuery = resp.nextPageToken
982 ? Object.assign({}, options, { pageToken: resp.nextPageToken })
983 : null;
984 callback(null, buckets, nextQuery, resp);
985 });
986 }
987 getHmacKeys(optionsOrCb, cb) {
988 const { options, callback } = (0, util_js_1.normalize)(optionsOrCb, cb);
989 const query = Object.assign({}, options);
990 const projectId = query.projectId || this.projectId;
991 delete query.projectId;
992 this.request({
993 uri: `/projects/${projectId}/hmacKeys`,
994 qs: query,
995 }, (err, resp) => {
996 if (err) {
997 callback(err, null, null, resp);
998 return;
999 }
1000 const itemsArray = resp.items ? resp.items : [];
1001 const hmacKeys = itemsArray.map((hmacKey) => {
1002 const hmacKeyInstance = this.hmacKey(hmacKey.accessId, {
1003 projectId: hmacKey.projectId,
1004 });
1005 hmacKeyInstance.metadata = hmacKey;
1006 return hmacKeyInstance;
1007 });
1008 const nextQuery = resp.nextPageToken
1009 ? Object.assign({}, options, { pageToken: resp.nextPageToken })
1010 : null;
1011 callback(null, hmacKeys, nextQuery, resp);
1012 });
1013 }
1014 /**
1015 * @typedef {array} GetServiceAccountResponse
1016 * @property {object} 0 The service account resource.
1017 * @property {object} 1 The full
1018 * {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount#resource| API response}.
1019 */
1020 /**
1021 * @callback GetServiceAccountCallback
1022 * @param {?Error} err Request error, if any.
1023 * @param {object} serviceAccount The serviceAccount resource.
1024 * @param {string} serviceAccount.emailAddress The service account email
1025 * address.
1026 * @param {object} apiResponse The full
1027 * {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount#resource| API response}.
1028 */
1029 /**
1030 * Get the email address of this project's Google Cloud Storage service
1031 * account.
1032 *
1033 * See {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount/get| Projects.serviceAccount: get API Documentation}
1034 * See {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount#resource| Projects.serviceAccount Resource}
1035 *
1036 * @param {object} [options] Configuration object.
1037 * @param {string} [options.userProject] User project to be billed for this
1038 * request.
1039 * @param {GetServiceAccountCallback} [callback] Callback function.
1040 * @returns {Promise<GetServiceAccountResponse>}
1041 *
1042 * @example
1043 * ```
1044 * const {Storage} = require('@google-cloud/storage');
1045 * const storage = new Storage();
1046 *
1047 * storage.getServiceAccount(function(err, serviceAccount, apiResponse) {
1048 * if (!err) {
1049 * const serviceAccountEmail = serviceAccount.emailAddress;
1050 * }
1051 * });
1052 *
1053 * //-
1054 * // If the callback is omitted, we'll return a Promise.
1055 * //-
1056 * storage.getServiceAccount().then(function(data) {
1057 * const serviceAccountEmail = data[0].emailAddress;
1058 * const apiResponse = data[1];
1059 * });
1060 * ```
1061 */
1062 getServiceAccount(optionsOrCallback, cb) {
1063 const { options, callback } = (0, util_js_1.normalize)(optionsOrCallback, cb);
1064 this.request({
1065 uri: `/projects/${this.projectId}/serviceAccount`,
1066 qs: options,
1067 }, (err, resp) => {
1068 if (err) {
1069 callback(err, null, resp);
1070 return;
1071 }
1072 const camelCaseResponse = {};
1073 for (const prop in resp) {
1074 // eslint-disable-next-line no-prototype-builtins
1075 if (resp.hasOwnProperty(prop)) {
1076 const camelCaseProp = prop.replace(/_(\w)/g, (_, match) => match.toUpperCase());
1077 camelCaseResponse[camelCaseProp] = resp[prop];
1078 }
1079 }
1080 callback(null, camelCaseResponse, resp);
1081 });
1082 }
1083 /**
1084 * Get a reference to an HmacKey object.
1085 * Note: this does not fetch the HMAC key's metadata. Use HmacKey#get() to
1086 * retrieve and populate the metadata.
1087 *
1088 * To get a reference to an HMAC key that's not created for a service
1089 * account in the same project used to instantiate the Storage client,
1090 * supply the project's ID as `projectId` in the `options` argument.
1091 *
1092 * @param {string} accessId The HMAC key's access ID.
1093 * @param {HmacKeyOptions} options HmacKey constructor options.
1094 * @returns {HmacKey}
1095 * @see HmacKey
1096 *
1097 * @example
1098 * ```
1099 * const {Storage} = require('@google-cloud/storage');
1100 * const storage = new Storage();
1101 * const hmacKey = storage.hmacKey('ACCESS_ID');
1102 * ```
1103 */
1104 hmacKey(accessId, options) {
1105 if (!accessId) {
1106 throw new Error(StorageExceptionMessages.HMAC_ACCESS_ID);
1107 }
1108 return new hmacKey_js_1.HmacKey(this, accessId, options);
1109 }
1110}
1111exports.Storage = Storage;
1112/**
1113 * {@link Bucket} class.
1114 *
1115 * @name Storage.Bucket
1116 * @see Bucket
1117 * @type {Constructor}
1118 */
1119Storage.Bucket = bucket_js_1.Bucket;
1120/**
1121 * {@link Channel} class.
1122 *
1123 * @name Storage.Channel
1124 * @see Channel
1125 * @type {Constructor}
1126 */
1127Storage.Channel = channel_js_1.Channel;
1128/**
1129 * {@link File} class.
1130 *
1131 * @name Storage.File
1132 * @see File
1133 * @type {Constructor}
1134 */
1135Storage.File = file_js_1.File;
1136/**
1137 * {@link HmacKey} class.
1138 *
1139 * @name Storage.HmacKey
1140 * @see HmacKey
1141 * @type {Constructor}
1142 */
1143Storage.HmacKey = hmacKey_js_1.HmacKey;
1144Storage.acl = {
1145 OWNER_ROLE: 'OWNER',
1146 READER_ROLE: 'READER',
1147 WRITER_ROLE: 'WRITER',
1148};
1149/*! Developer Documentation
1150 *
1151 * These methods can be auto-paginated.
1152 */
1153paginator_1.paginator.extend(Storage, ['getBuckets', 'getHmacKeys']);
1154/*! Developer Documentation
1155 *
1156 * All async methods (except for streams) will return a Promise in the event
1157 * that a callback is omitted.
1158 */
1159(0, promisify_1.promisifyAll)(Storage, {
1160 exclude: ['bucket', 'channel', 'hmacKey'],
1161});