UNPKG

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