mirror of
https://github.com/musix-org/musix-oss
synced 2025-07-02 12:03:37 +00:00
2355 lines
85 KiB
JavaScript
2355 lines
85 KiB
JavaScript
"use strict";
|
|
/**
|
|
* Copyright 2019 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const common_1 = require("@google-cloud/common");
|
|
const paginator_1 = require("@google-cloud/paginator");
|
|
const promisify_1 = require("@google-cloud/promisify");
|
|
const arrify = require("arrify");
|
|
const extend = require("extend");
|
|
const fs = require("fs");
|
|
const mime = require("mime-types");
|
|
const path = require("path");
|
|
const p_limit_1 = require("p-limit");
|
|
const util_1 = require("util");
|
|
const snakeize = require('snakeize');
|
|
const acl_1 = require("./acl");
|
|
const file_1 = require("./file");
|
|
const iam_1 = require("./iam");
|
|
const notification_1 = require("./notification");
|
|
/**
|
|
* The size of a file (in bytes) must be greater than this number to
|
|
* automatically trigger a resumable upload.
|
|
*
|
|
* @const {number}
|
|
* @private
|
|
*/
|
|
const RESUMABLE_THRESHOLD = 5000000;
|
|
/**
|
|
* Create a Bucket object to interact with a Cloud Storage bucket.
|
|
*
|
|
* @class
|
|
* @hideconstructor
|
|
*
|
|
* @param {Storage} storage A {@link Storage} instance.
|
|
* @param {string} name The name of the bucket.
|
|
* @param {object} [options] Configuration object.
|
|
* @param {string} [options.userProject] User project.
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*/
|
|
class Bucket extends common_1.ServiceObject {
|
|
constructor(storage, name, options) {
|
|
options = options || {};
|
|
// Allow for "gs://"-style input, and strip any trailing slashes.
|
|
name = name.replace(/^gs:\/\//, '').replace(/\/+$/, '');
|
|
const requestQueryObject = {};
|
|
const userProject = options.userProject;
|
|
if (typeof userProject === 'string') {
|
|
requestQueryObject.userProject = userProject;
|
|
}
|
|
const methods = {
|
|
/**
|
|
* Create a bucket.
|
|
*
|
|
* @method Bucket#create
|
|
* @param {CreateBucketRequest} [metadata] Metadata to set for the bucket.
|
|
* @param {CreateBucketCallback} [callback] Callback function.
|
|
* @returns {Promise<CreateBucketResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
* bucket.create(function(err, bucket, apiResponse) {
|
|
* if (!err) {
|
|
* // The bucket was created successfully.
|
|
* }
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.create().then(function(data) {
|
|
* const bucket = data[0];
|
|
* const apiResponse = data[1];
|
|
* });
|
|
*/
|
|
create: {
|
|
reqOpts: {
|
|
qs: requestQueryObject,
|
|
},
|
|
},
|
|
/**
|
|
* @typedef {object} DeleteBucketOptions Configuration options.
|
|
* @param {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @typedef {array} DeleteBucketResponse
|
|
* @property {object} 0 The full API response.
|
|
*/
|
|
/**
|
|
* @callback DeleteBucketCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* Delete the bucket.
|
|
*
|
|
* @see [Buckets: delete API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/buckets/delete}
|
|
*
|
|
* @method Bucket#delete
|
|
* @param {DeleteBucketOptions} [options] Configuration options.
|
|
* @param {DeleteBucketCallback} [callback] Callback function.
|
|
* @returns {Promise<DeleteBucketResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
* bucket.delete(function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.delete().then(function(data) {
|
|
* const apiResponse = data[0];
|
|
* });
|
|
*
|
|
* @example <caption>include:samples/buckets.js</caption>
|
|
* region_tag:storage_delete_bucket
|
|
* Another example:
|
|
*/
|
|
delete: {
|
|
reqOpts: {
|
|
qs: requestQueryObject,
|
|
},
|
|
},
|
|
/**
|
|
* @typedef {object} BucketExistsOptions Configuration options for Bucket#exists().
|
|
* @param {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @typedef {array} BucketExistsResponse
|
|
* @property {boolean} 0 Whether the {@link Bucket} exists.
|
|
*/
|
|
/**
|
|
* @callback BucketExistsCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {boolean} exists Whether the {@link Bucket} exists.
|
|
*/
|
|
/**
|
|
* Check if the bucket exists.
|
|
*
|
|
* @method Bucket#exists
|
|
* @param {BucketExistsOptions} [options] Configuration options.
|
|
* @param {BucketExistsCallback} [callback] Callback function.
|
|
* @returns {Promise<BucketExistsResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.exists(function(err, exists) {});
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.exists().then(function(data) {
|
|
* const exists = data[0];
|
|
* });
|
|
*/
|
|
exists: {
|
|
reqOpts: {
|
|
qs: requestQueryObject,
|
|
},
|
|
},
|
|
/**
|
|
* @typedef {object} [GetBucketOptions] Configuration options for Bucket#get()
|
|
* @property {boolean} [autoCreate] Automatically create the object if
|
|
* it does not exist. Default: `false`
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @typedef {array} GetBucketResponse
|
|
* @property {Bucket} 0 The {@link Bucket}.
|
|
* @property {object} 1 The full API response.
|
|
*/
|
|
/**
|
|
* @callback GetBucketCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {Bucket} bucket The {@link Bucket}.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* Get a bucket if it exists.
|
|
*
|
|
* You may optionally use this to "get or create" an object by providing
|
|
* an object with `autoCreate` set to `true`. Any extra configuration that
|
|
* is normally required for the `create` method must be contained within
|
|
* this object as well.
|
|
*
|
|
* @method Bucket#get
|
|
* @param {GetBucketOptions} [options] Configuration options.
|
|
* @param {GetBucketCallback} [callback] Callback function.
|
|
* @returns {Promise<GetBucketResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.get(function(err, bucket, apiResponse) {
|
|
* // `bucket.metadata` has been populated.
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.get().then(function(data) {
|
|
* const bucket = data[0];
|
|
* const apiResponse = data[1];
|
|
* });
|
|
*/
|
|
get: {
|
|
reqOpts: {
|
|
qs: requestQueryObject,
|
|
},
|
|
},
|
|
/**
|
|
* @typedef {array} GetBucketMetadataResponse
|
|
* @property {object} 0 The bucket metadata.
|
|
* @property {object} 1 The full API response.
|
|
*/
|
|
/**
|
|
* @callback GetBucketMetadataCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} metadata The bucket metadata.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* @typedef {object} GetBucketMetadataOptions Configuration options for Bucket#getMetadata().
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* Get the bucket's metadata.
|
|
*
|
|
* To set metadata, see {@link Bucket#setMetadata}.
|
|
*
|
|
* @see [Buckets: get API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/buckets/get}
|
|
*
|
|
* @method Bucket#getMetadata
|
|
* @param {GetBucketMetadataOptions} [options] Configuration options.
|
|
* @param {GetBucketMetadataCallback} [callback] Callback function.
|
|
* @returns {Promise<GetBucketMetadataResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.getMetadata(function(err, metadata, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.getMetadata().then(function(data) {
|
|
* const metadata = data[0];
|
|
* const apiResponse = data[1];
|
|
* });
|
|
*
|
|
* @example <caption>include:samples/requesterPays.js</caption>
|
|
* region_tag:storage_get_requester_pays_status
|
|
* Example of retrieving the requester pays status of a bucket:
|
|
*/
|
|
getMetadata: {
|
|
reqOpts: {
|
|
qs: requestQueryObject,
|
|
},
|
|
},
|
|
/**
|
|
* @typedef {object} SetBucketMetadataOptions Configuration options for Bucket#setMetadata().
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @typedef {array} SetBucketMetadataResponse
|
|
* @property {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* @callback SetBucketMetadataCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} metadata The bucket metadata.
|
|
*/
|
|
/**
|
|
* Set the bucket's metadata.
|
|
*
|
|
* @see [Buckets: patch API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch}
|
|
*
|
|
* @method Bucket#setMetadata
|
|
* @param {object<string, *>} metadata The metadata you wish to set.
|
|
* @param {SetBucketMetadataOptions} [options] Configuration options.
|
|
* @param {SetBucketMetadataCallback} [callback] Callback function.
|
|
* @returns {Promise<SetBucketMetadataResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* //-
|
|
* // Set website metadata field on the bucket.
|
|
* //-
|
|
* const metadata = {
|
|
* website: {
|
|
* mainPageSuffix: 'http://example.com',
|
|
* notFoundPage: 'http://example.com/404.html'
|
|
* }
|
|
* };
|
|
*
|
|
* bucket.setMetadata(metadata, function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // Enable versioning for your bucket.
|
|
* //-
|
|
* bucket.setMetadata({
|
|
* versioning: {
|
|
* enabled: true
|
|
* }
|
|
* }, function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // Enable KMS encryption for objects within this bucket.
|
|
* //-
|
|
* bucket.setMetadata({
|
|
* encryption: {
|
|
* defaultKmsKeyName: 'projects/grape-spaceship-123/...'
|
|
* }
|
|
* }, function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // Set the default event-based hold value for new objects in this
|
|
* // bucket.
|
|
* //-
|
|
* bucket.setMetadata({
|
|
* defaultEventBasedHold: true
|
|
* }, function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // Remove object lifecycle rules.
|
|
* //-
|
|
* bucket.setMetadata({
|
|
* lifecycle: null
|
|
* }, function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.setMetadata(metadata).then(function(data) {
|
|
* const apiResponse = data[0];
|
|
* });
|
|
*/
|
|
setMetadata: {
|
|
reqOpts: {
|
|
qs: requestQueryObject,
|
|
},
|
|
},
|
|
};
|
|
super({
|
|
parent: storage,
|
|
baseUrl: '/b',
|
|
id: name,
|
|
createMethod: storage.createBucket.bind(storage),
|
|
methods,
|
|
});
|
|
this.name = name;
|
|
this.storage = storage;
|
|
this.userProject = options.userProject;
|
|
this.acl = new acl_1.Acl({
|
|
request: this.request.bind(this),
|
|
pathPrefix: '/acl',
|
|
});
|
|
this.acl.default = new acl_1.Acl({
|
|
request: this.request.bind(this),
|
|
pathPrefix: '/defaultObjectAcl',
|
|
});
|
|
this.iam = new iam_1.Iam(this);
|
|
this.getFilesStream = paginator_1.paginator.streamify('getFiles');
|
|
}
|
|
/**
|
|
* @typedef {object} AddLifecycleRuleOptions Configuration options for Bucket#addLifecycleRule().
|
|
* @property {string} [append=true] The new rules will be appended to any
|
|
* pre-existing rules.
|
|
*/
|
|
/**
|
|
* Add an object lifecycle management rule to the bucket.
|
|
*
|
|
* By default, an Object Lifecycle Management rule provided to this method
|
|
* will be included to the existing policy. To replace all existing rules,
|
|
* supply the `options` argument, setting `append` to `false`.
|
|
*
|
|
* @see [Object Lifecycle Management]{@link https://cloud.google.com/storage/docs/lifecycle}
|
|
* @see [Buckets: patch API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch}
|
|
*
|
|
* @param {LifecycleRule} rule The new lifecycle rule to be added to objects
|
|
* in this bucket.
|
|
* @param {string} [rule.storageClass] When using the `setStorageClass`
|
|
* action, provide this option to dictate which storage class the object
|
|
* should update to.
|
|
* @param {AddLifecycleRuleOptions} [options] Configuration object.
|
|
* @param {boolean} [options.append=true] Append the new rule to the existing
|
|
* policy.
|
|
* @param {SetBucketMetadataCallback} [callback] Callback function.
|
|
* @returns {Promise<SetBucketMetadataResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* //-
|
|
* // Automatically have an object deleted from this bucket once it is 3 years
|
|
* // of age.
|
|
* //-
|
|
* bucket.addLifecycleRule({
|
|
* action: 'delete',
|
|
* condition: {
|
|
* age: 365 * 3 // Specified in days.
|
|
* }
|
|
* }, function(err, apiResponse) {
|
|
* if (err) {
|
|
* // Error handling omitted.
|
|
* }
|
|
*
|
|
* const lifecycleRules = bucket.metadata.lifecycle.rule;
|
|
*
|
|
* // Iterate over the Object Lifecycle Management rules on this bucket.
|
|
* lifecycleRules.forEach(lifecycleRule => {});
|
|
* });
|
|
*
|
|
* //-
|
|
* // By default, the rule you provide will be added to the existing policy.
|
|
* // Optionally, you can disable this behavior to replace all of the
|
|
* // pre-existing rules.
|
|
* //-
|
|
* const options = {
|
|
* append: false
|
|
* };
|
|
*
|
|
* bucket.addLifecycleRule({
|
|
* action: 'delete',
|
|
* condition: {
|
|
* age: 365 * 3 // Specified in days.
|
|
* }
|
|
* }, options, function(err, apiResponse) {
|
|
* if (err) {
|
|
* // Error handling omitted.
|
|
* }
|
|
*
|
|
* // All rules have been replaced with the new "delete" rule.
|
|
*
|
|
* // Iterate over the Object Lifecycle Management rules on this bucket.
|
|
* lifecycleRules.forEach(lifecycleRule => {});
|
|
* });
|
|
*
|
|
* //-
|
|
* // For objects created before 2018, "downgrade" the storage class.
|
|
* //-
|
|
* bucket.addLifecycleRule({
|
|
* action: 'setStorageClass',
|
|
* storageClass: 'COLDLINE',
|
|
* condition: {
|
|
* createdBefore: new Date('2018')
|
|
* }
|
|
* }, function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // Delete objects created before 2016 which have the Coldline storage
|
|
* // class.
|
|
* //-
|
|
* bucket.addLifecycleRule({
|
|
* action: 'delete',
|
|
* condition: {
|
|
* matchesStorageClass: [
|
|
* 'COLDLINE'
|
|
* ],
|
|
* createdBefore: new Date('2016')
|
|
* }
|
|
* }, function(err, apiResponse) {});
|
|
*/
|
|
addLifecycleRule(rule, optionsOrCallback, callback) {
|
|
let options;
|
|
if (typeof optionsOrCallback === 'function') {
|
|
callback = optionsOrCallback;
|
|
}
|
|
else if (optionsOrCallback) {
|
|
options = optionsOrCallback;
|
|
}
|
|
options = options || {};
|
|
callback = callback || common_1.util.noop;
|
|
const newLifecycleRules = arrify(rule).map(rule => {
|
|
if (typeof rule.action === 'object') {
|
|
// This is a raw-formatted rule object, the way the API expects.
|
|
// Just pass it through as-is.
|
|
return rule;
|
|
}
|
|
const apiFormattedRule = {};
|
|
apiFormattedRule.condition = {};
|
|
apiFormattedRule.action = {
|
|
type: rule.action,
|
|
};
|
|
// @TODO: Remove if the API becomes less picky.
|
|
if (rule.action === 'delete') {
|
|
apiFormattedRule.action.type = 'Delete';
|
|
}
|
|
if (rule.storageClass) {
|
|
apiFormattedRule.action.storageClass = rule.storageClass;
|
|
}
|
|
for (const condition in rule.condition) {
|
|
if (rule.condition[condition] instanceof Date) {
|
|
apiFormattedRule.condition[condition] = rule.condition[condition]
|
|
.toISOString()
|
|
.replace(/T.+$/, '');
|
|
}
|
|
else {
|
|
apiFormattedRule.condition[condition] = rule.condition[condition];
|
|
}
|
|
}
|
|
return apiFormattedRule;
|
|
});
|
|
if (options.append === false) {
|
|
this.setMetadata({ lifecycle: { rule: newLifecycleRules } }, callback);
|
|
return;
|
|
}
|
|
// The default behavior appends the previously-defined lifecycle rules with
|
|
// the new ones just passed in by the user.
|
|
this.getMetadata((err, metadata) => {
|
|
if (err) {
|
|
callback(err);
|
|
return;
|
|
}
|
|
const currentLifecycleRules = arrify(metadata.lifecycle && metadata.lifecycle.rule);
|
|
this.setMetadata({
|
|
lifecycle: {
|
|
rule: currentLifecycleRules.concat(newLifecycleRules),
|
|
},
|
|
}, callback);
|
|
});
|
|
}
|
|
/**
|
|
* @typedef {object} CombineOptions
|
|
* @property {string} [kmsKeyName] Resource name of the Cloud KMS key, of
|
|
* the form
|
|
* `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`,
|
|
* that will be used to encrypt the object. Overwrites the object
|
|
* metadata's `kms_key_name` value, if any.
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @callback CombineCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {File} newFile The new {@link File}.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* @typedef {array} CombineResponse
|
|
* @property {File} 0 The new {@link File}.
|
|
* @property {object} 1 The full API response.
|
|
*/
|
|
/**
|
|
* Combine multiple files into one new file.
|
|
*
|
|
* @see [Objects: compose API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/objects/compose}
|
|
*
|
|
* @throws {Error} if a non-array is provided as sources argument.
|
|
* @throws {Error} if less than two sources are provided.
|
|
* @throws {Error} if no destination is provided.
|
|
*
|
|
* @param {string[]|File[]} sources The source files that will be
|
|
* combined.
|
|
* @param {string|File} destination The file you would like the
|
|
* source files combined into.
|
|
* @param {CombineOptions} [options] Configuration options.
|
|
* @param {CombineCallback} [callback] Callback function.
|
|
* @returns {Promise<CombineResponse>}
|
|
*
|
|
* @example
|
|
* const logBucket = storage.bucket('log-bucket');
|
|
*
|
|
* const sources = [
|
|
* logBucket.file('2013-logs.txt'),
|
|
* logBucket.file('2014-logs.txt')
|
|
* ];
|
|
*
|
|
* const allLogs = logBucket.file('all-logs.txt');
|
|
*
|
|
* logBucket.combine(sources, allLogs, function(err, newFile, apiResponse) {
|
|
* // newFile === allLogs
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* logBucket.combine(sources, allLogs).then(function(data) {
|
|
* const newFile = data[0];
|
|
* const apiResponse = data[1];
|
|
* });
|
|
*/
|
|
combine(sources, destination, optionsOrCallback, callback) {
|
|
if (!Array.isArray(sources) || sources.length < 2) {
|
|
throw new Error('You must provide at least two source files.');
|
|
}
|
|
if (!destination) {
|
|
throw new Error('A destination file must be specified.');
|
|
}
|
|
let options = {};
|
|
if (typeof optionsOrCallback === 'function') {
|
|
callback = optionsOrCallback;
|
|
}
|
|
else if (optionsOrCallback) {
|
|
options = optionsOrCallback;
|
|
}
|
|
const convertToFile = (file) => {
|
|
if (file instanceof file_1.File) {
|
|
return file;
|
|
}
|
|
return this.file(file);
|
|
};
|
|
// tslint:disable-next-line:no-any
|
|
sources = sources.map(convertToFile);
|
|
const destinationFile = convertToFile(destination);
|
|
callback = callback || common_1.util.noop;
|
|
if (!destinationFile.metadata.contentType) {
|
|
const destinationContentType = mime.contentType(destinationFile.name);
|
|
if (destinationContentType) {
|
|
destinationFile.metadata.contentType = destinationContentType;
|
|
}
|
|
}
|
|
// Make the request from the destination File object.
|
|
destinationFile.request({
|
|
method: 'POST',
|
|
uri: '/compose',
|
|
json: {
|
|
destination: {
|
|
contentType: destinationFile.metadata.contentType,
|
|
},
|
|
sourceObjects: sources.map(source => {
|
|
const sourceObject = {
|
|
name: source.name,
|
|
};
|
|
if (source.metadata && source.metadata.generation) {
|
|
sourceObject.generation = source.metadata.generation;
|
|
}
|
|
return sourceObject;
|
|
}),
|
|
},
|
|
qs: options,
|
|
}, (err, resp) => {
|
|
if (err) {
|
|
callback(err, null, resp);
|
|
return;
|
|
}
|
|
callback(null, destinationFile, resp);
|
|
});
|
|
}
|
|
/**
|
|
* See a [Objects:
|
|
* watchAll request
|
|
* body](https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll).
|
|
*
|
|
* @typedef {object} CreateChannelConfig
|
|
* @property {string} address The address where notifications are
|
|
* delivered for this channel.
|
|
* @extends WatchAllOptions
|
|
*/
|
|
/**
|
|
* @typedef {object} CreateChannelOptions
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @typedef {array} CreateChannelResponse
|
|
* @property {Channel} 0 The new {@link Channel}.
|
|
* @property {object} 1 The full API response.
|
|
*/
|
|
/**
|
|
* @callback CreateChannelCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {Channel} channel The new {@link Channel}.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* Create a channel that will be notified when objects in this bucket changes.
|
|
*
|
|
* @throws {Error} If an ID is not provided.
|
|
* @throws {Error} If an address is not provided.
|
|
*
|
|
* @see [Objects: watchAll API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll}
|
|
*
|
|
* @param {string} id The ID of the channel to create.
|
|
* @param {CreateChannelConfig} config Configuration for creating channel.
|
|
* @param {CreateChannelOptions} [options] Configuration options.
|
|
* @param {CreateChannelCallback} [callback] Callback function.
|
|
* @returns {Promise<CreateChannelResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
* const id = 'new-channel-id';
|
|
*
|
|
* const config = {
|
|
* address: 'https://...'
|
|
* };
|
|
*
|
|
* bucket.createChannel(id, config, function(err, channel, apiResponse) {
|
|
* if (!err) {
|
|
* // Channel created successfully.
|
|
* }
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.createChannel(id, config).then(function(data) {
|
|
* const channel = data[0];
|
|
* const apiResponse = data[1];
|
|
* });
|
|
*/
|
|
createChannel(id, config, optionsOrCallback, callback) {
|
|
if (typeof id !== 'string') {
|
|
throw new Error('An ID is required to create a channel.');
|
|
}
|
|
if (typeof config.address !== 'string') {
|
|
throw new Error('An address is required to create a channel.');
|
|
}
|
|
let options = {};
|
|
if (typeof optionsOrCallback === 'function') {
|
|
callback = optionsOrCallback;
|
|
}
|
|
else if (optionsOrCallback) {
|
|
options = optionsOrCallback;
|
|
}
|
|
this.request({
|
|
method: 'POST',
|
|
uri: '/o/watch',
|
|
json: Object.assign({
|
|
id,
|
|
type: 'web_hook',
|
|
}, config),
|
|
qs: options,
|
|
}, (err, apiResponse) => {
|
|
if (err) {
|
|
callback(err, null, apiResponse);
|
|
return;
|
|
}
|
|
const resourceId = apiResponse.resourceId;
|
|
const channel = this.storage.channel(id, resourceId);
|
|
channel.metadata = apiResponse;
|
|
callback(null, channel, apiResponse);
|
|
});
|
|
}
|
|
/**
|
|
* Metadata to set for the Notification.
|
|
*
|
|
* @typedef {object} CreateNotificationOptions
|
|
* @property {object} [customAttributes] An optional list of additional
|
|
* attributes to attach to each Cloud PubSub message published for this
|
|
* notification subscription.
|
|
* @property {string[]} [eventTypes] If present, only send notifications about
|
|
* listed event types. If empty, sent notifications for all event types.
|
|
* @property {string} [objectNamePrefix] If present, only apply this
|
|
* notification configuration to object names that begin with this prefix.
|
|
* @property {string} [payloadFormat] The desired content of the Payload.
|
|
* Defaults to `JSON_API_V1`.
|
|
*
|
|
* Acceptable values are:
|
|
* - `JSON_API_V1`
|
|
*
|
|
* - `NONE`
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @callback CreateNotificationCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {Notification} notification The new {@link Notification}.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* @typedef {array} CreateNotificationResponse
|
|
* @property {Notification} 0 The new {@link Notification}.
|
|
* @property {object} 1 The full API response.
|
|
*/
|
|
/**
|
|
* Creates a notification subscription for the bucket.
|
|
*
|
|
* @see [Notifications: insert]{@link https://cloud.google.com/storage/docs/json_api/v1/notifications/insert}
|
|
*
|
|
* @param {Topic|string} topic The Cloud PubSub topic to which this
|
|
* subscription publishes. If the project ID is omitted, the current
|
|
* project ID will be used.
|
|
*
|
|
* Acceptable formats are:
|
|
* - `projects/grape-spaceship-123/topics/my-topic`
|
|
*
|
|
* - `my-topic`
|
|
* @param {CreateNotificationOptions} [options] Metadata to set for the
|
|
* notification.
|
|
* @param {CreateNotificationCallback} [callback] Callback function.
|
|
* @returns {Promise<CreateNotificationResponse>}
|
|
* @throws {Error} If a valid topic is not provided.
|
|
* @see Notification#create
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const myBucket = storage.bucket('my-bucket');
|
|
*
|
|
* const callback = function(err, notification, apiResponse) {
|
|
* if (!err) {
|
|
* // The notification was created successfully.
|
|
* }
|
|
* };
|
|
*
|
|
* myBucket.createNotification('my-topic', callback);
|
|
*
|
|
* //-
|
|
* // Configure the nofiication by providing Notification metadata.
|
|
* //-
|
|
* const metadata = {
|
|
* objectNamePrefix: 'prefix-'
|
|
* };
|
|
*
|
|
* myBucket.createNotification('my-topic', metadata, callback);
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* myBucket.createNotification('my-topic').then(function(data) {
|
|
* const notification = data[0];
|
|
* const apiResponse = data[1];
|
|
* });
|
|
*
|
|
* @example <caption>include:samples/notifications.js</caption>
|
|
* region_tag:storage_create_notification
|
|
* Another example:
|
|
*/
|
|
createNotification(topic, optionsOrCallback, callback) {
|
|
let options = {};
|
|
if (typeof optionsOrCallback === 'function') {
|
|
callback = optionsOrCallback;
|
|
}
|
|
else if (optionsOrCallback) {
|
|
options = optionsOrCallback;
|
|
}
|
|
const topicIsObject = topic !== null && typeof topic === 'object';
|
|
if (topicIsObject && common_1.util.isCustomType(topic, 'pubsub/topic')) {
|
|
// tslint:disable-next-line:no-any
|
|
topic = topic.name;
|
|
}
|
|
if (typeof topic !== 'string') {
|
|
throw new Error('A valid topic name is required.');
|
|
}
|
|
const body = Object.assign({ topic }, options);
|
|
if (body.topic.indexOf('projects') !== 0) {
|
|
body.topic = 'projects/{{projectId}}/topics/' + body.topic;
|
|
}
|
|
body.topic = '//pubsub.googleapis.com/' + body.topic;
|
|
if (!body.payloadFormat) {
|
|
body.payloadFormat = 'JSON_API_V1';
|
|
}
|
|
const query = {};
|
|
if (body.userProject) {
|
|
query.userProject = body.userProject;
|
|
delete body.userProject;
|
|
}
|
|
this.request({
|
|
method: 'POST',
|
|
uri: '/notificationConfigs',
|
|
json: snakeize(body),
|
|
qs: query,
|
|
}, (err, apiResponse) => {
|
|
if (err) {
|
|
callback(err, null, apiResponse);
|
|
return;
|
|
}
|
|
const notification = this.notification(apiResponse.id);
|
|
notification.metadata = apiResponse;
|
|
callback(null, notification, apiResponse);
|
|
});
|
|
}
|
|
/**
|
|
* @typedef {object} DeleteFilesOptions Query object. See {@link Bucket#getFiles}
|
|
* for all of the supported properties.
|
|
* @property {boolean} [force] Suppress errors until all files have been
|
|
* processed.
|
|
*/
|
|
/**
|
|
* @callback DeleteFilesCallback
|
|
* @param {?Error|?Error[]} err Request error, if any, or array of errors from
|
|
* files that were not able to be deleted.
|
|
* @param {object} [apiResponse] The full API response.
|
|
*/
|
|
/**
|
|
* Iterate over the bucket's files, calling `file.delete()` on each.
|
|
*
|
|
* <strong>This is not an atomic request.</strong> A delete attempt will be
|
|
* made for each file individually. Any one can fail, in which case only a
|
|
* portion of the files you intended to be deleted would have.
|
|
*
|
|
* Operations are performed in parallel, up to 10 at once. The first error
|
|
* breaks the loop and will execute the provided callback with it. Specify
|
|
* `{ force: true }` to suppress the errors until all files have had a chance
|
|
* to be processed.
|
|
*
|
|
* The `query` object passed as the first argument will also be passed to
|
|
* {@link Bucket#getFiles}.
|
|
*
|
|
* @see [Objects: delete API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/objects/delete}
|
|
*
|
|
* @param {DeleteFilesOptions} [query] Query object. See {@link Bucket#getFiles}
|
|
* @param {DeleteFilesCallback} [callback] Callback function.
|
|
* @returns {Promise}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* //-
|
|
* // Delete all of the files in the bucket.
|
|
* //-
|
|
* bucket.deleteFiles(function(err) {});
|
|
*
|
|
* //-
|
|
* // By default, if a file cannot be deleted, this method will stop deleting
|
|
* // files from your bucket. You can override this setting with `force:
|
|
* // true`.
|
|
* //-
|
|
* bucket.deleteFiles({
|
|
* force: true
|
|
* }, function(errors) {
|
|
* // `errors`:
|
|
* // Array of errors if any occurred, otherwise null.
|
|
* });
|
|
*
|
|
* //-
|
|
* // The first argument to this method acts as a query to
|
|
* // {@link Bucket#getFiles}. As an example, you can delete files
|
|
* // which match a prefix.
|
|
* //-
|
|
* bucket.deleteFiles({
|
|
* prefix: 'images/'
|
|
* }, function(err) {
|
|
* if (!err) {
|
|
* // All files in the `images` directory have been deleted.
|
|
* }
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.deleteFiles().then(function() {});
|
|
*/
|
|
deleteFiles(queryOrCallback, callback) {
|
|
let query = {};
|
|
if (typeof queryOrCallback === 'function') {
|
|
callback = queryOrCallback;
|
|
}
|
|
else if (queryOrCallback) {
|
|
query = queryOrCallback;
|
|
}
|
|
const MAX_PARALLEL_LIMIT = 10;
|
|
const errors = [];
|
|
const deleteFile = (file) => {
|
|
return file.delete(query).catch(err => {
|
|
if (!query.force) {
|
|
throw err;
|
|
}
|
|
errors.push(err);
|
|
});
|
|
};
|
|
this.getFiles(query)
|
|
.then(([files]) => {
|
|
const limit = p_limit_1.default(MAX_PARALLEL_LIMIT);
|
|
const promises = files.map(file => {
|
|
return limit(() => deleteFile(file));
|
|
});
|
|
return Promise.all(promises);
|
|
})
|
|
.then(() => callback(errors.length > 0 ? errors : null), callback);
|
|
}
|
|
/**
|
|
* @typedef {array} DeleteLabelsResponse
|
|
* @property {object} 0 The full API response.
|
|
*/
|
|
/**
|
|
* @callback DeleteLabelsCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} metadata Bucket's metadata.
|
|
*/
|
|
/**
|
|
* Delete one or more labels from this bucket.
|
|
*
|
|
* @param {string|string[]} labels The labels to delete. If no labels are
|
|
* provided, all of the labels are removed.
|
|
* @param {DeleteLabelsCallback} [callback] Callback function.
|
|
* @returns {Promise<DeleteLabelsResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* //-
|
|
* // Delete all of the labels from this bucket.
|
|
* //-
|
|
* bucket.deleteLabels(function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // Delete a single label.
|
|
* //-
|
|
* bucket.deleteLabels('labelone', function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // Delete a specific set of labels.
|
|
* //-
|
|
* bucket.deleteLabels([
|
|
* 'labelone',
|
|
* 'labeltwo'
|
|
* ], function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.deleteLabels().then(function(data) {
|
|
* const apiResponse = data[0];
|
|
* });
|
|
*/
|
|
deleteLabels(labelsOrCallback, callback) {
|
|
let labels = new Array();
|
|
if (typeof labelsOrCallback === 'function') {
|
|
callback = labelsOrCallback;
|
|
}
|
|
else if (labelsOrCallback) {
|
|
labels = arrify(labelsOrCallback);
|
|
}
|
|
const deleteLabels = (labels) => {
|
|
const nullLabelMap = labels.reduce((nullLabelMap, labelKey) => {
|
|
nullLabelMap[labelKey] = null;
|
|
return nullLabelMap;
|
|
}, {});
|
|
this.setLabels(nullLabelMap, callback);
|
|
};
|
|
if (labels.length === 0) {
|
|
this.getLabels((err, labels) => {
|
|
if (err) {
|
|
callback(err);
|
|
return;
|
|
}
|
|
deleteLabels(Object.keys(labels));
|
|
});
|
|
}
|
|
else {
|
|
deleteLabels(labels);
|
|
}
|
|
}
|
|
/**
|
|
* @typedef {array} DisableRequesterPaysResponse
|
|
* @property {object} 0 The full API response.
|
|
*/
|
|
/**
|
|
* @callback DisableRequesterPaysCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* <div class="notice">
|
|
* <strong>Early Access Testers Only</strong>
|
|
* <p>
|
|
* This feature is not yet widely-available.
|
|
* </p>
|
|
* </div>
|
|
*
|
|
* Disable `requesterPays` functionality from this bucket.
|
|
*
|
|
* @param {DisableRequesterPaysCallback} [callback] Callback function.
|
|
* @returns {Promise<DisableRequesterPaysCallback>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.disableRequesterPays(function(err, apiResponse) {
|
|
* if (!err) {
|
|
* // requesterPays functionality disabled successfully.
|
|
* }
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.disableRequesterPays().then(function(data) {
|
|
* const apiResponse = data[0];
|
|
* });
|
|
*
|
|
* @example <caption>include:samples/requesterPays.js</caption>
|
|
* region_tag:storage_disable_requester_pays
|
|
* Example of disabling requester pays:
|
|
*/
|
|
disableRequesterPays(callback) {
|
|
this.setMetadata({
|
|
billing: {
|
|
requesterPays: false,
|
|
},
|
|
}, callback || common_1.util.noop);
|
|
}
|
|
/**
|
|
* @typedef {array} EnableRequesterPaysResponse
|
|
* @property {object} 0 The full API response.
|
|
*/
|
|
/**
|
|
* @callback EnableRequesterPaysCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* <div class="notice">
|
|
* <strong>Early Access Testers Only</strong>
|
|
* <p>
|
|
* This feature is not yet widely-available.
|
|
* </p>
|
|
* </div>
|
|
*
|
|
* Enable `requesterPays` functionality for this bucket. This enables you, the
|
|
* bucket owner, to have the requesting user assume the charges for the access
|
|
* to your bucket and its contents.
|
|
*
|
|
* @param {EnableRequesterPaysCallback} [callback] Callback function.
|
|
* @returns {Promise<EnableRequesterPaysResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.enableRequesterPays(function(err, apiResponse) {
|
|
* if (!err) {
|
|
* // requesterPays functionality enabled successfully.
|
|
* }
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.enableRequesterPays().then(function(data) {
|
|
* const apiResponse = data[0];
|
|
* });
|
|
*
|
|
* @example <caption>include:samples/requesterPays.js</caption>
|
|
* region_tag:storage_enable_requester_pays
|
|
* Example of enabling requester pays:
|
|
*/
|
|
enableRequesterPays(callback) {
|
|
this.setMetadata({
|
|
billing: {
|
|
requesterPays: true,
|
|
},
|
|
}, callback || common_1.util.noop);
|
|
}
|
|
/**
|
|
* Create a {@link File} object. See {@link File} to see how to handle
|
|
* the different use cases you may have.
|
|
*
|
|
* @param {string} name The name of the file in this bucket.
|
|
* @param {object} [options] Configuration options.
|
|
* @param {string|number} [options.generation] Only use a specific revision of
|
|
* this file.
|
|
* @param {string} [options.encryptionKey] A custom encryption key. See
|
|
* [Customer-supplied Encryption
|
|
* Keys](https://cloud.google.com/storage/docs/encryption#customer-supplied).
|
|
* @param {string} [options.kmsKeyName] The name of the Cloud KMS key that will
|
|
* be used to encrypt the object. Must be in the format:
|
|
* `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`.
|
|
* KMS key ring must use the same location as the bucket.
|
|
* @returns {File}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
* const file = bucket.file('my-existing-file.png');
|
|
*/
|
|
file(name, options) {
|
|
if (!name) {
|
|
throw Error('A file name must be specified.');
|
|
}
|
|
return new file_1.File(this, name, options);
|
|
}
|
|
/**
|
|
* @typedef {array} GetFilesResponse
|
|
* @property {File[]} 0 Array of {@link File} instances.
|
|
*/
|
|
/**
|
|
* @callback GetFilesCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {File[]} files Array of {@link File} instances.
|
|
*/
|
|
/**
|
|
* Query object for listing files.
|
|
*
|
|
* @typedef {object} GetFilesOptions
|
|
* @property {boolean} [autoPaginate=true] Have pagination handled
|
|
* automatically.
|
|
* @property {string} [delimiter] Results will contain only objects whose
|
|
* names, aside from the prefix, do not contain delimiter. Objects whose
|
|
* names, aside from the prefix, contain delimiter will have their name
|
|
* truncated after the delimiter, returned in `apiResponse.prefixes`.
|
|
* Duplicate prefixes are omitted.
|
|
* @property {string} [directory] Filter results based on a directory name, or
|
|
* more technically, a "prefix".
|
|
* @property {string} [prefix] Filter results to objects whose names begin
|
|
* with this prefix.
|
|
* @property {number} [maxApiCalls] Maximum number of API calls to make.
|
|
* @property {number} [maxResults] Maximum number of items plus prefixes to
|
|
* return.
|
|
* @property {string} [pageToken] A previously-returned page token
|
|
* representing part of the larger set of results to view.
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
* @property {boolean} [versions] If true, returns File objects scoped to
|
|
* their versions.
|
|
*/
|
|
/**
|
|
* Get {@link File} objects for the files currently in the bucket.
|
|
*
|
|
* @see [Objects: list API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/objects/list}
|
|
*
|
|
* @param {GetFilesOptions} [query] Query object for listing files.
|
|
* @param {GetFilesCallback} [callback] Callback function.
|
|
* @returns {Promise<GetFilesResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.getFiles(function(err, files) {
|
|
* if (!err) {
|
|
* // files is an array of File objects.
|
|
* }
|
|
* });
|
|
*
|
|
* //-
|
|
* // If your bucket has versioning enabled, you can get all of your files
|
|
* // scoped to their generation.
|
|
* //-
|
|
* bucket.getFiles({
|
|
* versions: true
|
|
* }, function(err, files) {
|
|
* // Each file is scoped to its generation.
|
|
* });
|
|
*
|
|
* //-
|
|
* // To control how many API requests are made and page through the results
|
|
* // manually, set `autoPaginate` to `false`.
|
|
* //-
|
|
* const callback = function(err, files, nextQuery, apiResponse) {
|
|
* if (nextQuery) {
|
|
* // More results exist.
|
|
* bucket.getFiles(nextQuery, callback);
|
|
* }
|
|
*
|
|
* // The `metadata` property is populated for you with the metadata at the
|
|
* // time of fetching.
|
|
* files[0].metadata;
|
|
*
|
|
* // However, in cases where you are concerned the metadata could have
|
|
* // changed, use the `getMetadata` method.
|
|
* files[0].getMetadata(function(err, metadata) {});
|
|
* };
|
|
*
|
|
* bucket.getFiles({
|
|
* autoPaginate: false
|
|
* }, callback);
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.getFiles().then(function(data) {
|
|
* const files = data[0];
|
|
* });
|
|
*
|
|
* @example <caption>include:samples/files.js</caption>
|
|
* region_tag:storage_list_files
|
|
* Another example:
|
|
*
|
|
* @example <caption>include:samples/files.js</caption>
|
|
* region_tag:storage_list_files_with_prefix
|
|
* Example of listing files, filtered by a prefix:
|
|
*/
|
|
getFiles(queryOrCallback, callback) {
|
|
let query = typeof queryOrCallback === 'object' ? queryOrCallback : {};
|
|
if (!callback) {
|
|
callback = queryOrCallback;
|
|
}
|
|
query = Object.assign({}, query);
|
|
if (query.directory) {
|
|
query.prefix = `${query.directory}/`.replace(/\/*$/, '/');
|
|
delete query.directory;
|
|
}
|
|
this.request({
|
|
uri: '/o',
|
|
qs: query,
|
|
}, (err, resp) => {
|
|
if (err) {
|
|
// tslint:disable-next-line:no-any
|
|
callback(err, null, null, resp);
|
|
return;
|
|
}
|
|
const files = arrify(resp.items).map((file) => {
|
|
const options = {};
|
|
if (query.versions) {
|
|
options.generation = file.generation;
|
|
}
|
|
if (file.kmsKeyName) {
|
|
options.kmsKeyName = file.kmsKeyName;
|
|
}
|
|
const fileInstance = this.file(file.name, options);
|
|
fileInstance.metadata = file;
|
|
return fileInstance;
|
|
});
|
|
let nextQuery = null;
|
|
if (resp.nextPageToken) {
|
|
nextQuery = Object.assign({}, query, {
|
|
pageToken: resp.nextPageToken,
|
|
});
|
|
}
|
|
// tslint:disable-next-line:no-any
|
|
callback(null, files, nextQuery, resp);
|
|
});
|
|
}
|
|
/**
|
|
* @typedef {object} GetLabelsOptions Configuration options for Bucket#getLabels().
|
|
* @param {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @typedef {array} GetLabelsResponse
|
|
* @property {object} 0 Object of labels currently set on this bucket.
|
|
*/
|
|
/**
|
|
* @callback GetLabelsCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} labels Object of labels currently set on this bucket.
|
|
*/
|
|
/**
|
|
* Get the labels currently set on this bucket.
|
|
*
|
|
* @param {object} [options] Configuration options.
|
|
* @param {string} [options.userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
* @param {GetLabelsCallback} [callback] Callback function.
|
|
* @returns {Promise<GetLabelsCallback>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.getLabels(function(err, labels) {
|
|
* if (err) {
|
|
* // Error handling omitted.
|
|
* }
|
|
*
|
|
* // labels = {
|
|
* // label: 'labelValue',
|
|
* // ...
|
|
* // }
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.getLabels().then(function(data) {
|
|
* const labels = data[0];
|
|
* });
|
|
*/
|
|
getLabels(optionsOrCallback, callback) {
|
|
let options = {};
|
|
if (typeof optionsOrCallback === 'function') {
|
|
callback = optionsOrCallback;
|
|
}
|
|
else if (optionsOrCallback) {
|
|
options = optionsOrCallback;
|
|
}
|
|
this.getMetadata(options, (err, metadata) => {
|
|
if (err) {
|
|
callback(err, null);
|
|
return;
|
|
}
|
|
callback(null, metadata.labels || {});
|
|
});
|
|
}
|
|
/**
|
|
* @typedef {object} GetNotificationOptions Configuration options for Bucket#getNotification().
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @callback GetNotificationsCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {Notification[]} notifications Array of {@link Notification}
|
|
* instances.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* @typedef {array} GetNotificationsResponse
|
|
* @property {Notification[]} 0 Array of {@link Notification} instances.
|
|
* @property {object} 1 The full API response.
|
|
*/
|
|
/**
|
|
* Retrieves a list of notification subscriptions for a given bucket.
|
|
*
|
|
* @see [Notifications: list]{@link https://cloud.google.com/storage/docs/json_api/v1/notifications/list}
|
|
*
|
|
* @param {GetNotificationsOptions} [options] Configuration options.
|
|
* @param {GetNotificationsCallback} [callback] Callback function.
|
|
* @returns {Promise<GetNotificationsResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('my-bucket');
|
|
*
|
|
* bucket.getNotifications(function(err, notifications, apiResponse) {
|
|
* if (!err) {
|
|
* // notifications is an array of Notification objects.
|
|
* }
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.getNotifications().then(function(data) {
|
|
* const notifications = data[0];
|
|
* const apiResponse = data[1];
|
|
* });
|
|
*
|
|
* @example <caption>include:samples/notifications.js</caption>
|
|
* region_tag:storage_list_notifications
|
|
* Another example:
|
|
*/
|
|
getNotifications(optionsOrCallback, callback) {
|
|
let options = {};
|
|
if (typeof optionsOrCallback === 'function') {
|
|
callback = optionsOrCallback;
|
|
}
|
|
else if (optionsOrCallback) {
|
|
options = optionsOrCallback;
|
|
}
|
|
this.request({
|
|
uri: '/notificationConfigs',
|
|
qs: options,
|
|
}, (err, resp) => {
|
|
if (err) {
|
|
callback(err, null, resp);
|
|
return;
|
|
}
|
|
const notifications = arrify(resp.items).map((notification) => {
|
|
const notificationInstance = this.notification(notification.id);
|
|
notificationInstance.metadata = notification;
|
|
return notificationInstance;
|
|
});
|
|
callback(null, notifications, resp);
|
|
});
|
|
}
|
|
/**
|
|
* @callback BucketLockCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* Lock a previously-defined retention policy. This will prevent changes to
|
|
* the policy.
|
|
*
|
|
* @throws {Error} if a metageneration is not provided.
|
|
*
|
|
* @param {Number|String} metageneration The bucket's metageneration. This is
|
|
* accesssible from calling {@link File#getMetadata}.
|
|
* @param {BucketLockCallback} [callback] Callback function.
|
|
* @returns {Promise<BucketLockResponse>}
|
|
*
|
|
* @example
|
|
* const storage = require('@google-cloud/storage')();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* const metageneration = 2;
|
|
*
|
|
* bucket.lock(metageneration, function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.lock(metageneration).then(function(data) {
|
|
* const apiResponse = data[0];
|
|
* });
|
|
*/
|
|
lock(metageneration, callback) {
|
|
const metatype = typeof metageneration;
|
|
if (metatype !== 'number' && metatype !== 'string') {
|
|
throw new Error('A metageneration must be provided.');
|
|
}
|
|
this.request({
|
|
method: 'POST',
|
|
uri: '/lockRetentionPolicy',
|
|
qs: {
|
|
ifMetagenerationMatch: metageneration,
|
|
},
|
|
}, callback);
|
|
}
|
|
/**
|
|
* @typedef {array} MakeBucketPrivateResponse
|
|
* @property {File[]} 0 List of files made private.
|
|
*/
|
|
/**
|
|
* @callback MakeBucketPrivateCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {File[]} files List of files made private.
|
|
*/
|
|
/**
|
|
* @typedef {object} MakeBucketPrivateOptions
|
|
* @param {boolean} [includeFiles=false] Make each file in the bucket
|
|
* private.
|
|
* @param {boolean} [force] Queue errors occurred while making files
|
|
* private until all files have been processed.
|
|
* @param {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* Make the bucket listing private.
|
|
*
|
|
* You may also choose to make the contents of the bucket private by
|
|
* specifying `includeFiles: true`. This will automatically run
|
|
* {@link File#makePrivate} for every file in the bucket.
|
|
*
|
|
* When specifying `includeFiles: true`, use `force: true` to delay execution
|
|
* of your callback until all files have been processed. By default, the
|
|
* callback is executed after the first error. Use `force` to queue such
|
|
* errors until all files have been processed, after which they will be
|
|
* returned as an array as the first argument to your callback.
|
|
*
|
|
* NOTE: This may cause the process to be long-running and use a high number
|
|
* of requests. Use with caution.
|
|
*
|
|
* @see [Buckets: patch API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch}
|
|
*
|
|
* @param {MakeBucketPrivateOptions} [options] Configuration options.
|
|
* @param {MakeBucketPrivateCallback} [callback] Callback function.
|
|
* @returns {Promise<MakeBucketPrivateResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* //-
|
|
* // Make the bucket private.
|
|
* //-
|
|
* bucket.makePrivate(function(err) {});
|
|
*
|
|
* //-
|
|
* // Make the bucket and its contents private.
|
|
* //-
|
|
* const opts = {
|
|
* includeFiles: true
|
|
* };
|
|
*
|
|
* bucket.makePrivate(opts, function(err, files) {
|
|
* // `err`:
|
|
* // The first error to occur, otherwise null.
|
|
* //
|
|
* // `files`:
|
|
* // Array of files successfully made private in the bucket.
|
|
* });
|
|
*
|
|
* //-
|
|
* // Make the bucket and its contents private, using force to suppress errors
|
|
* // until all files have been processed.
|
|
* //-
|
|
* const opts = {
|
|
* includeFiles: true,
|
|
* force: true
|
|
* };
|
|
*
|
|
* bucket.makePrivate(opts, function(errors, files) {
|
|
* // `errors`:
|
|
* // Array of errors if any occurred, otherwise null.
|
|
* //
|
|
* // `files`:
|
|
* // Array of files successfully made private in the bucket.
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.makePrivate(opts).then(function(data) {
|
|
* const files = data[0];
|
|
* });
|
|
*/
|
|
makePrivate(optionsOrCallback, callback) {
|
|
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
|
|
callback =
|
|
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
|
|
options.private = true;
|
|
const query = {
|
|
predefinedAcl: 'projectPrivate',
|
|
};
|
|
if (options.userProject) {
|
|
query.userProject = options.userProject;
|
|
}
|
|
this.setMetadata({
|
|
// You aren't allowed to set both predefinedAcl & acl properties on
|
|
// a bucket so acl must explicitly be nullified.
|
|
acl: null,
|
|
}, query)
|
|
.then(() => {
|
|
if (options.includeFiles) {
|
|
return util_1.promisify(this.makeAllFilesPublicPrivate_).call(this, options);
|
|
}
|
|
return [];
|
|
})
|
|
.then(files => callback(null, files), callback);
|
|
}
|
|
/**
|
|
* @typedef {object} MakeBucketPublicOptions
|
|
* @param {boolean} [includeFiles=false] Make each file in the bucket
|
|
* private.
|
|
* @param {boolean} [force] Queue errors occurred while making files
|
|
* private until all files have been processed.
|
|
*/
|
|
/**
|
|
* @callback MakeBucketPublicCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {File[]} files List of files made public.
|
|
*/
|
|
/**
|
|
* @typedef {array} MakeBucketPublicResponse
|
|
* @property {File[]} 0 List of files made public.
|
|
*/
|
|
/**
|
|
* Make the bucket publicly readable.
|
|
*
|
|
* You may also choose to make the contents of the bucket publicly readable by
|
|
* specifying `includeFiles: true`. This will automatically run
|
|
* {@link File#makePublic} for every file in the bucket.
|
|
*
|
|
* When specifying `includeFiles: true`, use `force: true` to delay execution
|
|
* of your callback until all files have been processed. By default, the
|
|
* callback is executed after the first error. Use `force` to queue such
|
|
* errors until all files have been processed, after which they will be
|
|
* returned as an array as the first argument to your callback.
|
|
*
|
|
* NOTE: This may cause the process to be long-running and use a high number
|
|
* of requests. Use with caution.
|
|
*
|
|
* @see [Buckets: patch API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch}
|
|
*
|
|
* @param {MakeBucketPublicOptions} [options] Configuration options.
|
|
* @param {MakeBucketPublicCallback} [callback] Callback function.
|
|
* @returns {Promise<MakeBucketPublicResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* //-
|
|
* // Make the bucket publicly readable.
|
|
* //-
|
|
* bucket.makePublic(function(err) {});
|
|
*
|
|
* //-
|
|
* // Make the bucket and its contents publicly readable.
|
|
* //-
|
|
* const opts = {
|
|
* includeFiles: true
|
|
* };
|
|
*
|
|
* bucket.makePublic(opts, function(err, files) {
|
|
* // `err`:
|
|
* // The first error to occur, otherwise null.
|
|
* //
|
|
* // `files`:
|
|
* // Array of files successfully made public in the bucket.
|
|
* });
|
|
*
|
|
* //-
|
|
* // Make the bucket and its contents publicly readable, using force to
|
|
* // suppress errors until all files have been processed.
|
|
* //-
|
|
* const opts = {
|
|
* includeFiles: true,
|
|
* force: true
|
|
* };
|
|
*
|
|
* bucket.makePublic(opts, function(errors, files) {
|
|
* // `errors`:
|
|
* // Array of errors if any occurred, otherwise null.
|
|
* //
|
|
* // `files`:
|
|
* // Array of files successfully made public in the bucket.
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.makePublic(opts).then(function(data) {
|
|
* const files = data[0];
|
|
* });
|
|
*/
|
|
makePublic(optionsOrCallback, callback) {
|
|
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
|
|
callback =
|
|
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
|
|
const req = extend(true, { public: true }, options);
|
|
this.acl
|
|
.add({
|
|
entity: 'allUsers',
|
|
role: 'READER',
|
|
})
|
|
.then(() => {
|
|
return this.acl.default.add({
|
|
entity: 'allUsers',
|
|
role: 'READER',
|
|
});
|
|
})
|
|
.then(() => {
|
|
if (req.includeFiles) {
|
|
return util_1.promisify(this.makeAllFilesPublicPrivate_).call(this, req);
|
|
}
|
|
return [];
|
|
})
|
|
.then(files => callback(null, files), callback);
|
|
}
|
|
/**
|
|
* Get a reference to a Cloud Pub/Sub Notification.
|
|
*
|
|
* @param {string} id ID of notification.
|
|
* @returns {Notification}
|
|
* @see Notification
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('my-bucket');
|
|
* const notification = bucket.notification('1');
|
|
*/
|
|
notification(id) {
|
|
if (!id) {
|
|
throw new Error('You must supply a notification ID.');
|
|
}
|
|
return new notification_1.Notification(this, id);
|
|
}
|
|
/**
|
|
* Remove an already-existing retention policy from this bucket, if it is not
|
|
* locked.
|
|
*
|
|
* @param {SetBucketMetadataCallback} [callback] Callback function.
|
|
* @returns {Promise<SetBucketMetadataResponse>}
|
|
*
|
|
* @example
|
|
* const storage = require('@google-cloud/storage')();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.removeRetentionPeriod(function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.removeRetentionPeriod().then(function(data) {
|
|
* const apiResponse = data[0];
|
|
* });
|
|
*/
|
|
removeRetentionPeriod(callback) {
|
|
this.setMetadata({
|
|
retentionPolicy: null,
|
|
}, callback);
|
|
}
|
|
/**
|
|
* Makes request and applies userProject query parameter if necessary.
|
|
*
|
|
* @private
|
|
*
|
|
* @param {object} reqOpts - The request options.
|
|
* @param {function} callback - The callback function.
|
|
*/
|
|
request(reqOpts, callback) {
|
|
if (this.userProject && (!reqOpts.qs || !reqOpts.qs.userProject)) {
|
|
reqOpts.qs = extend(reqOpts.qs, { userProject: this.userProject });
|
|
}
|
|
return super.request(reqOpts, callback);
|
|
}
|
|
/**
|
|
* @typedef {array} SetLabelsResponse
|
|
* @property {object} 0 The bucket metadata.
|
|
*/
|
|
/**
|
|
* @callback SetLabelsCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} metadata The bucket metadata.
|
|
*/
|
|
/**
|
|
* @typedef {object} SetLabelsOptions Configuration options for Bucket#setLabels().
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* Set labels on the bucket.
|
|
*
|
|
* This makes an underlying call to {@link Bucket#setMetadata}, which
|
|
* is a PATCH request. This means an individual label can be overwritten, but
|
|
* unmentioned labels will not be touched.
|
|
*
|
|
* @param {object<string, string>} labels Labels to set on the bucket.
|
|
* @param {object} [options] Configuration options.
|
|
* @param {SetLabelsCallback} [callback] Callback function.
|
|
* @returns {Promise<SetLabelsResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* const labels = {
|
|
* labelone: 'labelonevalue',
|
|
* labeltwo: 'labeltwovalue'
|
|
* };
|
|
*
|
|
* bucket.setLabels(labels, function(err, metadata) {
|
|
* if (!err) {
|
|
* // Labels set successfully.
|
|
* }
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.setLabels(labels).then(function(data) {
|
|
* const metadata = data[0];
|
|
* });
|
|
*/
|
|
setLabels(labels, optionsOrCallback, callback) {
|
|
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
|
|
callback =
|
|
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
|
|
callback = callback || common_1.util.noop;
|
|
this.setMetadata({ labels }, options, callback);
|
|
}
|
|
/**
|
|
* Lock all objects contained in the bucket, based on their creation time. Any
|
|
* attempt to overwrite or delete objects younger than the retention period
|
|
* will result in a `PERMISSION_DENIED` error.
|
|
*
|
|
* An unlocked retention policy can be modified or removed from the bucket via
|
|
* {@link File#removeRetentionPeriod} and {@link File#setRetentionPeriod}. A
|
|
* locked retention policy cannot be removed or shortened in duration for the
|
|
* lifetime of the bucket. Attempting to remove or decrease period of a locked
|
|
* retention policy will result in a `PERMISSION_DENIED` error. You can still
|
|
* increase the policy.
|
|
*
|
|
* @param {*} duration In seconds, the minimum retention time for all objects
|
|
* contained in this bucket.
|
|
* @param {SetBucketMetadataCallback} [callback] Callback function.
|
|
* @returns {Promise<SetBucketMetadataResponse>}
|
|
*
|
|
* @example
|
|
* const storage = require('@google-cloud/storage')();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* const DURATION_SECONDS = 15780000; // 6 months.
|
|
*
|
|
* //-
|
|
* // Lock the objects in this bucket for 6 months.
|
|
* //-
|
|
* bucket.setRetentionPeriod(DURATION_SECONDS, function(err, apiResponse) {});
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.setRetentionPeriod(DURATION_SECONDS).then(function(data) {
|
|
* const apiResponse = data[0];
|
|
* });
|
|
*/
|
|
setRetentionPeriod(duration, callback) {
|
|
this.setMetadata({
|
|
retentionPolicy: {
|
|
retentionPeriod: duration,
|
|
},
|
|
}, callback);
|
|
}
|
|
/**
|
|
* @typedef {object} SetBucketStorageClassOptions
|
|
* @param {string} [userProject] - The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @callback SetBucketStorageClassCallback
|
|
* @param {?Error} err Request error, if any.
|
|
*/
|
|
/**
|
|
* Set the default storage class for new files in this bucket.
|
|
*
|
|
* @see [Storage Classes]{@link https://cloud.google.com/storage/docs/storage-classes}
|
|
*
|
|
* @param {string} storageClass The new storage class. (`standard`,
|
|
* `nearline`, `coldline`, or `durable_reduced_availability`).
|
|
* **Note:** The storage classes `multi_regional` and `regional`
|
|
* are now legacy and will be deprecated in the future.
|
|
* @param {object} [options] Configuration options.
|
|
* @param {string} [options.userProject] - The ID of the project which will be
|
|
* billed for the request.
|
|
* @param {SetStorageClassCallback} [callback] Callback function.
|
|
* @returns {Promise}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.setStorageClass('regional', function(err, apiResponse) {
|
|
* if (err) {
|
|
* // Error handling omitted.
|
|
* }
|
|
*
|
|
* // The storage class was updated successfully.
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.setStorageClass('regional').then(function() {});
|
|
*/
|
|
setStorageClass(storageClass, optionsOrCallback, callback) {
|
|
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
|
|
callback =
|
|
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
|
|
// In case we get input like `storageClass`, convert to `storage_class`.
|
|
storageClass = storageClass
|
|
.replace(/-/g, '_')
|
|
.replace(/([a-z])([A-Z])/g, (_, low, up) => {
|
|
return low + '_' + up;
|
|
})
|
|
.toUpperCase();
|
|
this.setMetadata({ storageClass }, options, callback);
|
|
}
|
|
/**
|
|
* Set a user project to be billed for all requests made from this Bucket
|
|
* object and any files referenced from this Bucket object.
|
|
*
|
|
* @param {string} userProject The user project.
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* bucket.setUserProject('grape-spaceship-123');
|
|
*/
|
|
setUserProject(userProject) {
|
|
this.userProject = userProject;
|
|
const methods = [
|
|
'create',
|
|
'delete',
|
|
'exists',
|
|
'get',
|
|
'getMetadata',
|
|
'setMetadata',
|
|
];
|
|
methods.forEach(method => {
|
|
const methodConfig = this.methods[method];
|
|
if (typeof methodConfig === 'object') {
|
|
if (typeof methodConfig.reqOpts === 'object') {
|
|
extend(methodConfig.reqOpts.qs, { userProject });
|
|
}
|
|
else {
|
|
methodConfig.reqOpts = {
|
|
qs: { userProject },
|
|
};
|
|
}
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* @typedef {object} UploadOptions Configuration options for Bucket#upload().
|
|
* @param {string|File} [options.destination] The place to save
|
|
* your file. If given a string, the file will be uploaded to the bucket
|
|
* using the string as a filename. When given a File object, your local
|
|
* file will be uploaded to the File object's bucket and under the File
|
|
* object's name. Lastly, when this argument is omitted, the file is uploaded
|
|
* to your bucket using the name of the local file.
|
|
* @param {string} [options.encryptionKey] A custom encryption key. See
|
|
* [Customer-supplied Encryption
|
|
* Keys](https://cloud.google.com/storage/docs/encryption#customer-supplied).
|
|
* @param {boolean} [options.gzip] Automatically gzip the file. This will set
|
|
* `options.metadata.contentEncoding` to `gzip`.
|
|
* @param {string} [options.kmsKeyName] The name of the Cloud KMS key that will
|
|
* be used to encrypt the object. Must be in the format:
|
|
* `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`.
|
|
* @param {object} [options.metadata] See an
|
|
* [Objects: insert request
|
|
* body](https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON).
|
|
* @param {string} [options.offset] The starting byte of the upload stream, for
|
|
* resuming an interrupted upload. Defaults to 0.
|
|
* @param {string} [options.predefinedAcl] Apply a predefined set of access
|
|
* controls to this object.
|
|
*
|
|
* Acceptable values are:
|
|
* - **`authenticatedRead`** - Object owner gets `OWNER` access, and
|
|
* `allAuthenticatedUsers` get `READER` access.
|
|
*
|
|
* - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and
|
|
* project team owners get `OWNER` access.
|
|
*
|
|
* - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project
|
|
* team owners get `READER` access.
|
|
*
|
|
* - **`private`** - Object owner gets `OWNER` access.
|
|
*
|
|
* - **`projectPrivate`** - Object owner gets `OWNER` access, and project
|
|
* team members get access according to their roles.
|
|
*
|
|
* - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers`
|
|
* get `READER` access.
|
|
* @param {boolean} [options.private] Make the uploaded file private. (Alias for
|
|
* `options.predefinedAcl = 'private'`)
|
|
* @param {boolean} [options.public] Make the uploaded file public. (Alias for
|
|
* `options.predefinedAcl = 'publicRead'`)
|
|
* @param {boolean} [options.resumable] Force a resumable upload. (default:
|
|
* true for files larger than 5 MB).
|
|
* @param {string} [options.uri] The URI for an already-created resumable
|
|
* upload. See {@link File#createResumableUpload}.
|
|
* @param {string} [options.userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
* @param {string|boolean} [options.validation] Possible values: `"md5"`,
|
|
* `"crc32c"`, or `false`. By default, data integrity is validated with an
|
|
* MD5 checksum for maximum reliability. CRC32c will provide better
|
|
* performance with less reliability. You may also choose to skip
|
|
* validation completely, however this is **not recommended**.
|
|
*/
|
|
/**
|
|
* @typedef {array} UploadResponse
|
|
* @property {object} 0 The uploaded {@link File}.
|
|
* @property {object} 1 The full API response.
|
|
*/
|
|
/**
|
|
* @callback UploadCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {object} file The uploaded {@link File}.
|
|
* @param {object} apiResponse The full API response.
|
|
*/
|
|
/**
|
|
* Upload a file to the bucket. This is a convenience method that wraps
|
|
* {@link File#createWriteStream}.
|
|
*
|
|
* You can specify whether or not an upload is resumable by setting
|
|
* `options.resumable`. *Resumable uploads are enabled by default if your
|
|
* input file is larger than 5 MB.*
|
|
*
|
|
* For faster crc32c computation, you must manually install
|
|
* [`fast-crc32c`](http://www.gitnpm.com/fast-crc32c):
|
|
*
|
|
* $ npm install --save fast-crc32c
|
|
*
|
|
* @see [Upload Options (Simple or Resumable)]{@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload#uploads}
|
|
* @see [Objects: insert API Documentation]{@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert}
|
|
*
|
|
* @param {string} pathString The fully qualified path to the file you
|
|
* wish to upload to your bucket.
|
|
* @param {UploadOptions} [options] Configuration options.
|
|
* @param {UploadCallback} [callback] Callback function.
|
|
* @returns {Promise<UploadResponse>}
|
|
*
|
|
* @example
|
|
* const {Storage} = require('@google-cloud/storage');
|
|
* const storage = new Storage();
|
|
* const bucket = storage.bucket('albums');
|
|
*
|
|
* //-
|
|
* // Upload a file from a local path.
|
|
* //-
|
|
* bucket.upload('/local/path/image.png', function(err, file, apiResponse) {
|
|
* // Your bucket now contains:
|
|
* // - "image.png" (with the contents of `/local/path/image.png')
|
|
*
|
|
* // `file` is an instance of a File object that refers to your new file.
|
|
* });
|
|
*
|
|
*
|
|
* //-
|
|
* // It's not always that easy. You will likely want to specify the filename
|
|
* // used when your new file lands in your bucket.
|
|
* //
|
|
* // You may also want to set metadata or customize other options.
|
|
* //-
|
|
* const options = {
|
|
* destination: 'new-image.png',
|
|
* resumable: true,
|
|
* validation: 'crc32c',
|
|
* metadata: {
|
|
* metadata: {
|
|
* event: 'Fall trip to the zoo'
|
|
* }
|
|
* }
|
|
* };
|
|
*
|
|
* bucket.upload('local-image.png', options, function(err, file) {
|
|
* // Your bucket now contains:
|
|
* // - "new-image.png" (with the contents of `local-image.png')
|
|
*
|
|
* // `file` is an instance of a File object that refers to your new file.
|
|
* });
|
|
*
|
|
* //-
|
|
* // You can also have a file gzip'd on the fly.
|
|
* //-
|
|
* bucket.upload('index.html', { gzip: true }, function(err, file) {
|
|
* // Your bucket now contains:
|
|
* // - "index.html" (automatically compressed with gzip)
|
|
*
|
|
* // Downloading the file with `file.download` will automatically decode
|
|
* the
|
|
* // file.
|
|
* });
|
|
*
|
|
* //-
|
|
* // You may also re-use a File object, {File}, that references
|
|
* // the file you wish to create or overwrite.
|
|
* //-
|
|
* const options = {
|
|
* destination: bucket.file('existing-file.png'),
|
|
* resumable: false
|
|
* };
|
|
*
|
|
* bucket.upload('local-img.png', options, function(err, newFile) {
|
|
* // Your bucket now contains:
|
|
* // - "existing-file.png" (with the contents of `local-img.png')
|
|
*
|
|
* // Note:
|
|
* // The `newFile` parameter is equal to `file`.
|
|
* });
|
|
*
|
|
* //-
|
|
* // To use
|
|
* // <a
|
|
* href="https://cloud.google.com/storage/docs/encryption#customer-supplied">
|
|
* // Customer-supplied Encryption Keys</a>, provide the `encryptionKey`
|
|
* option.
|
|
* //-
|
|
* const crypto = require('crypto');
|
|
* const encryptionKey = crypto.randomBytes(32);
|
|
*
|
|
* bucket.upload('img.png', {
|
|
* encryptionKey: encryptionKey
|
|
* }, function(err, newFile) {
|
|
* // `img.png` was uploaded with your custom encryption key.
|
|
*
|
|
* // `newFile` is already configured to use the encryption key when making
|
|
* // operations on the remote object.
|
|
*
|
|
* // However, to use your encryption key later, you must create a `File`
|
|
* // instance with the `key` supplied:
|
|
* const file = bucket.file('img.png', {
|
|
* encryptionKey: encryptionKey
|
|
* });
|
|
*
|
|
* // Or with `file#setEncryptionKey`:
|
|
* const file = bucket.file('img.png');
|
|
* file.setEncryptionKey(encryptionKey);
|
|
* });
|
|
*
|
|
* //-
|
|
* // If the callback is omitted, we'll return a Promise.
|
|
* //-
|
|
* bucket.upload('local-image.png').then(function(data) {
|
|
* const file = data[0];
|
|
* });
|
|
*
|
|
* To upload a file from a URL, use {@link File#createWriteStream}.
|
|
*
|
|
* @example <caption>include:samples/files.js</caption>
|
|
* region_tag:storage_upload_file
|
|
* Another example:
|
|
*
|
|
* @example <caption>include:samples/encryption.js</caption>
|
|
* region_tag:storage_upload_encrypted_file
|
|
* Example of uploading an encrypted file:
|
|
*/
|
|
upload(pathString, optionsOrCallback, callback) {
|
|
// tslint:disable-next-line:no-any
|
|
if (global['GCLOUD_SANDBOX_ENV']) {
|
|
return;
|
|
}
|
|
let options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
|
|
callback =
|
|
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
|
|
options = Object.assign({
|
|
metadata: {},
|
|
}, options);
|
|
let newFile;
|
|
if (options.destination instanceof file_1.File) {
|
|
newFile = options.destination;
|
|
}
|
|
else if (options.destination != null &&
|
|
typeof options.destination === 'string') {
|
|
// Use the string as the name of the file.
|
|
newFile = this.file(options.destination, {
|
|
encryptionKey: options.encryptionKey,
|
|
kmsKeyName: options.kmsKeyName,
|
|
});
|
|
}
|
|
else {
|
|
// Resort to using the name of the incoming file.
|
|
const destination = path.basename(pathString);
|
|
newFile = this.file(destination, {
|
|
encryptionKey: options.encryptionKey,
|
|
kmsKeyName: options.kmsKeyName,
|
|
});
|
|
}
|
|
const contentType = mime.contentType(path.basename(pathString));
|
|
if (contentType && !options.metadata.contentType) {
|
|
options.metadata.contentType = contentType;
|
|
}
|
|
if (options.resumable != null && typeof options.resumable === 'boolean') {
|
|
upload();
|
|
}
|
|
else {
|
|
// Determine if the upload should be resumable if it's over the threshold.
|
|
fs.stat(pathString, (err, fd) => {
|
|
if (err) {
|
|
callback(err);
|
|
return;
|
|
}
|
|
options.resumable = fd.size > RESUMABLE_THRESHOLD;
|
|
upload();
|
|
});
|
|
}
|
|
function upload() {
|
|
fs.createReadStream(pathString)
|
|
.on('error', callback)
|
|
.pipe(newFile.createWriteStream(options))
|
|
.on('error', callback)
|
|
.on('finish', () => {
|
|
callback(null, newFile, newFile.metadata);
|
|
});
|
|
}
|
|
}
|
|
/**
|
|
* @private
|
|
*
|
|
* @typedef {object} MakeAllFilesPublicPrivateOptions
|
|
* @property {boolean} [force] Suppress errors until all files have been
|
|
* processed.
|
|
* @property {boolean} [private] Make files private.
|
|
* @property {boolean} [public] Make files public.
|
|
* @property {string} [userProject] The ID of the project which will be
|
|
* billed for the request.
|
|
*/
|
|
/**
|
|
* @private
|
|
*
|
|
* @callback SetBucketMetadataCallback
|
|
* @param {?Error} err Request error, if any.
|
|
* @param {File[]} files Files that were updated.
|
|
*/
|
|
/**
|
|
* @typedef {array} MakeAllFilesPublicPrivateResponse
|
|
* @property {File[]} 0 List of files affected.
|
|
*/
|
|
/**
|
|
* Iterate over all of a bucket's files, calling `file.makePublic()` (public)
|
|
* or `file.makePrivate()` (private) on each.
|
|
*
|
|
* Operations are performed in parallel, up to 10 at once. The first error
|
|
* breaks the loop, and will execute the provided callback with it. Specify
|
|
* `{ force: true }` to suppress the errors.
|
|
*
|
|
* @private
|
|
*
|
|
* @param {MakeAllFilesPublicPrivateOptions} [options] Configuration options.
|
|
* @param {MakeAllFilesPublicPrivateCallback} callback Callback function.
|
|
*
|
|
* @return {Promise<MakeAllFilesPublicPrivateResponse>}
|
|
*/
|
|
makeAllFilesPublicPrivate_(optionsOrCallback, callback) {
|
|
const MAX_PARALLEL_LIMIT = 10;
|
|
const errors = [];
|
|
const updatedFiles = [];
|
|
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
|
|
callback =
|
|
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
|
|
const processFile = async (file) => {
|
|
try {
|
|
await (options.public ? file.makePublic() : file.makePrivate(options));
|
|
updatedFiles.push(file);
|
|
}
|
|
catch (e) {
|
|
if (!options.force) {
|
|
throw e;
|
|
}
|
|
errors.push(e);
|
|
}
|
|
};
|
|
this.getFiles(options)
|
|
.then(([files]) => {
|
|
const limit = p_limit_1.default(MAX_PARALLEL_LIMIT);
|
|
const promises = files.map(file => {
|
|
return limit(() => processFile(file));
|
|
});
|
|
return Promise.all(promises);
|
|
})
|
|
.then(() => callback(errors.length > 0 ? errors : null, updatedFiles), err => callback(err, updatedFiles));
|
|
}
|
|
getId() {
|
|
return this.id;
|
|
}
|
|
}
|
|
exports.Bucket = Bucket;
|
|
/*! Developer Documentation
|
|
*
|
|
* These methods can be auto-paginated.
|
|
*/
|
|
paginator_1.paginator.extend(Bucket, 'getFiles');
|
|
/*! Developer Documentation
|
|
*
|
|
* All async methods (except for streams) will return a Promise in the event
|
|
* that a callback is omitted.
|
|
*/
|
|
promisify_1.promisifyAll(Bucket, {
|
|
exclude: ['request', 'file', 'notification'],
|
|
});
|
|
//# sourceMappingURL=bucket.js.map
|