UNPKG

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