@google-cloud/bigtable
Version:
Cloud Bigtable Client Library for Node.js
1,186 lines • 48.7 kB
JavaScript
"use strict";
// Copyright 2016 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
//
// https://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 });
exports.Instance = void 0;
const promisify_1 = require("@google-cloud/promisify");
const stream_1 = require("stream");
const arrify = require("arrify");
const is = require("is");
const extend = require("extend");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const pumpify = require('pumpify');
const concat = require('concat-stream');
const snakeCase = require("lodash.snakecase");
const app_profile_1 = require("./app-profile");
const cluster_1 = require("./cluster");
const family_1 = require("./family");
const table_1 = require("./table");
const backup_1 = require("./backup");
const cluster_2 = require("./utils/cluster");
const authorized_view_1 = require("./authorized-view");
const protobufreadertransformer_1 = require("./execute-query/protobufreadertransformer");
const queryresultrowtransformer_1 = require("./execute-query/queryresultrowtransformer");
const parameterparsing_1 = require("./execute-query/parameterparsing");
const metadataconsumer_1 = require("./execute-query/metadataconsumer");
const executequerystatemachine_1 = require("./execute-query/executequerystatemachine");
const preparedstatement_1 = require("./execute-query/preparedstatement");
/**
* Create an Instance object to interact with a Cloud Bigtable instance.
*
* @class
* @param {Bigtable} bigtable The parent {@link Bigtable} object of this
* instance.
* @param {string} id Id of the instance.
*
* @example
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
* const instance = bigtable.instance('my-instance');
* ```
*/
class Instance {
bigtable;
id;
name;
metadata;
constructor(bigtable, id) {
this.bigtable = bigtable;
let name;
if (id.includes('/')) {
if (id.startsWith(`${bigtable.projectName}/instances/`)) {
name = id;
}
else {
throw new Error(`Instance id '${id}' is not formatted correctly.
Please use the format 'my-instance' or '${bigtable.projectName}/instances/my-instance'.`);
}
}
else {
name = `${bigtable.projectName}/instances/${id}`;
}
this.id = name.split('/').pop();
this.name = name;
}
/**
* Maps the instance type to the proper integer.
*
* @private
*
* @param {string} type The instance type (production, development).
* @returns {number}
*
* @example
* ```
* Instance.getTypeType_('production');
* // 1
* ```
*/
static getTypeType_(type) {
const types = {
unspecified: 0,
production: 1,
development: 2,
};
if (typeof type === 'string') {
type = type.toLowerCase();
}
return types[type] || types.unspecified;
}
/**
* Get a reference to a Bigtable App Profile.
*
* @param {string} name The name of the app profile.
* @returns {AppProfile}
*/
appProfile(name) {
return new app_profile_1.AppProfile(this, name);
}
/**
* Create an instance.
*
* @param {object} options See {@link Bigtable#createInstance}.
* @param {object} [options.gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {Instance} callback.instance The newly created
* instance.
* @param {Operation} callback.operation An operation object that can be used
* to check the status of the request.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_create_instance
*/
create(options, callback) {
this.bigtable.createInstance(this.id, options, callback);
}
/**
* Create an app profile.
*
* @param {string} id The name to be used when referring to the new
* app profile within its instance.
* @param {object} options AppProfile creation options.
* @param {'any'|Cluster} options.routing The routing policy for all
* read/write requests which use this app profile. This can be either the
* string 'any' or a cluster of an instance. This value is required when
* creating the app profile and optional when setting the metadata.
* @param {object} [options.gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
* @param {boolean} [options.allowTransactionalWrites] Whether or not
* CheckAndMutateRow and ReadModifyWriteRow requests are allowed by this
* app profile. It is unsafe to send these requests to the same
* table/row/column in multiple clusters. This is only used when the
* routing value is a cluster.
* @param {string} [options.description] The long form description of the use
* case for this AppProfile.
* @param {string} [options.ignoreWarnings] Whether to ignore safety checks
* when creating the app profile
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this request.
* @param {Cluster} callback.appProfile The newly created app profile.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_create_app_profile
*/
createAppProfile(id, optionsOrCallback, cb) {
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
if (!options.routing) {
throw new Error('An app profile must contain a routing policy.');
}
const appProfile = app_profile_1.AppProfile.formatAppProfile_(options);
const reqOpts = {
parent: this.name,
appProfileId: id,
appProfile,
};
if (is.boolean(options.ignoreWarnings)) {
reqOpts.ignoreWarnings = options.ignoreWarnings;
}
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'createAppProfile',
reqOpts,
gaxOpts: options.gaxOptions,
}, (...args) => {
if (args[1]) {
args.splice(1, 0, this.appProfile(id));
}
callback(...args);
});
}
/**
* Create a cluster.
*
* @param {string} id The id to be used when referring to the new
* cluster within its instance.
* @param {object} options Cluster creation options.
* @param {object} [options.gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
* @param {object} [options.encryption] CMEK configuration options.
* @param {string} options.encryption.kmsKeyName The KMS key name.
* @param {string} [options.key] Alias for `options.encryption.kmsKeyName`.
* @param {string} options.location The location where this cluster's nodes
* and storage reside. For best performance clients should be located as
* as close as possible to this cluster. Currently only zones are
* supported.
* @param {number} options.nodes The number of nodes allocated to this
* cluster. More nodes enable higher throughput and more consistent
* performance.
* @param {string} [options.storage] The type of storage used by this cluster
* to serve its parent instance's tables. Options are 'hdd' or 'ssd'.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this request.
* @param {Cluster} callback.cluster The newly created
* cluster.
* @param {Operation} callback.operation An operation object that can be used
* to check the status of the request.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_create_cluster
*/
createCluster(id, optionsOrCallback, cb) {
const options = typeof optionsOrCallback === 'object'
? optionsOrCallback
: {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
const reqOpts = {
parent: this.name,
clusterId: id,
};
cluster_2.ClusterUtils.validateClusterMetadata(options);
if (!is.empty(options)) {
reqOpts.cluster = cluster_2.ClusterUtils.getClusterBaseConfigWithFullLocation(options, this.bigtable.projectId, undefined);
}
if (typeof options.key !== 'undefined' &&
typeof options.encryption !== 'undefined') {
throw new Error('The cluster cannot have both `encryption` and `key` defined.');
}
if (options.key) {
reqOpts.cluster.encryptionConfig = {
kmsKeyName: options.key,
};
}
if (options.encryption) {
reqOpts.cluster.encryptionConfig = options.encryption;
}
if (options.storage) {
const storageType = cluster_1.Cluster.getStorageType_(options.storage);
reqOpts.cluster.defaultStorageType = storageType;
}
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'createCluster',
reqOpts,
gaxOpts: options.gaxOptions,
}, (...args) => {
if (args[1]) {
args.splice(1, 0, this.cluster(id));
}
callback(...args);
});
}
/**
* Create a table on your Bigtable instance.
*
* @see [Designing Your Schema]{@link https://cloud.google.com/bigtable/docs/schema-design}
* @see [Splitting Keys]{@link https://cloud.google.com/bigtable/docs/managing-tables#splits}
*
* @throws {error} If a id is not provided.
*
* @param {string} id Unique identifier of the table.
* @param {object} [options] Table creation options.
* @param {object|string[]} [options.families] Column families to be created
* within the table.
* @param {object} [options.gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {string[]} [options.splits] Initial
* {@link https://cloud.google.com/bigtable/docs/managing-tables#splits| split keys}.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this request.
* @param {Table} callback.table The newly created table.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_create_table
*/
createTable(id, optionsOrCallback, cb) {
if (!id) {
throw new Error('An id is required to create a table.');
}
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
const reqOpts = {
parent: this.name,
tableId: id,
table: {
// The granularity at which timestamps are stored in the table.
// Currently only milliseconds is supported, so it's not
// configurable.
granularity: 0,
},
};
if (options.splits) {
reqOpts.initialSplits = options.splits.map(key => ({
key,
}));
}
if (options.families) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const columnFamilies = options.families.reduce((families, family) => {
if (typeof family === 'string') {
family = {
name: family,
};
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const columnFamily = (families[family.name] = {});
if (family.rule) {
columnFamily.gcRule = family_1.Family.formatRule_(family.rule);
}
return families;
}, {});
reqOpts.table.columnFamilies = columnFamilies;
}
this.bigtable.request({
client: 'BigtableTableAdminClient',
method: 'createTable',
reqOpts,
gaxOpts: options.gaxOptions,
}, (...args) => {
if (args[1]) {
const table = this.table(args[1].name.split('/').pop());
table.metadata = args[1];
args.splice(1, 0, table);
}
callback(...args);
});
}
/**
* Get a reference to a Bigtable Cluster.
*
* @param {string} id The id of the cluster.
* @returns {Cluster}
*/
cluster(id) {
return new cluster_1.Cluster(this, id);
}
/**
* Delete the instance.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} [callback] The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_del_instance
*/
delete(optionsOrCallback, cb) {
const gaxOptions = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'deleteInstance',
reqOpts: {
name: this.name,
},
gaxOpts: gaxOptions,
}, callback);
}
/**
* Check if an instance exists.
*
* @param {object} [gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {boolean} callback.exists Whether the instance exists or not.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_exists_instance
*/
exists(optionsOrCallback, cb) {
const gaxOptions = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
this.getMetadata(gaxOptions, err => {
if (err) {
if (err.code === 5) {
callback(null, false);
return;
}
callback(err);
return;
}
callback(null, true);
});
}
/**
* Get an instance if it exists.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} callback The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {Instance} callback.instance The Instance object.
* @param {object} callback.apiResponse The resource as it exists in the API.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_get_instance
*/
get(optionsOrCallback, cb) {
const gaxOptions = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
this.getMetadata(gaxOptions, (err, metadata) => {
if (err) {
callback(err, undefined, metadata);
}
else {
callback(null, this, metadata);
}
});
}
/**
* Get App Profile objects for this instance.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} callback The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {AppProfile[]} callback.appProfiles List of all AppProfiles.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_get_app_profiles
*/
getAppProfiles(optionsOrCallback, cb) {
const gaxOpts = typeof optionsOrCallback === 'object'
? extend(true, {}, optionsOrCallback)
: {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
const reqOpts = {
parent: this.name,
};
if (is.number(gaxOpts.pageSize)) {
reqOpts.pageSize = gaxOpts.pageSize;
}
delete gaxOpts.pageSize;
if (gaxOpts.pageToken) {
reqOpts.pageToken = gaxOpts.pageToken;
}
delete gaxOpts.pageToken;
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'listAppProfiles',
reqOpts,
gaxOpts,
}, (err, resp) => {
if (err) {
callback(err);
return;
}
const appProfiles = resp.map(appProfileObj => {
const appProfile = this.appProfile(appProfileObj.name.split('/').pop());
appProfile.metadata = appProfileObj;
return appProfile;
});
callback(null, appProfiles, resp);
});
}
/**
* Get {@link AppProfile} objects for all the App Profiles in your
* Cloud Bigtable instance as a readable object stream.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* {@link Instance#getAppProfiles} for a complete list of options.
* @returns {stream}
*
* @example
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
* const instance = bigtable.instance('my-instance');
*
* instance.getAppProfilesStream()
* .on('error', console.error)
* .on('data', function(appProfile) {
* // appProfile is a AppProfile object.
* })
* .on('end', () => {
* // All appProfiles retrieved.
* });
*
* //-
* // If you anticipate many results, you can end a stream early to prevent
* // unnecessary processing and API requests.
* //-
* instance.getAppProfilesStream()
* .on('data', function(appProfile) {
* this.end();
* });
* ```
*/
getAppProfilesStream(gaxOptions = {}) {
const reqOpts = {
parent: this.name,
};
const gaxOpts = extend(true, {}, gaxOptions);
if (is.number(gaxOpts.pageSize)) {
reqOpts.pageSize = gaxOpts.pageSize;
}
delete gaxOpts.pageSize;
if (gaxOpts.pageToken) {
reqOpts.pageToken = gaxOpts.pageToken;
}
delete gaxOpts.pageToken;
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
const transformToAppProfile = (chunk, enc, callback) => {
const appProfile = self.appProfile(chunk.name.split('/').pop());
appProfile.metadata = chunk;
callback(null, appProfile);
};
let failedLocations = [];
const flush = (callback) => {
if (failedLocations.length > 0) {
callback(new Error(`Resources from the following locations are currently not available\n${JSON.stringify(failedLocations)}`));
}
else {
callback();
}
};
const stream = this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'listAppProfilesStream',
reqOpts,
gaxOpts,
});
stream.on('response', apiResp => {
if (arrify(apiResp.failedLocations).length > 0) {
failedLocations = failedLocations.concat(apiResp.failedLocations);
}
});
return pumpify.obj([
stream,
new stream_1.Transform({
objectMode: true,
transform: transformToAppProfile,
flush,
}),
]);
}
/**
* Get Cloud Bigtable Backup instances within this instance. This returns both
* completed and pending backups.
*
* @param {GetBackupsOptions | GetBackupsCallback} [optionsOrCallback]
* @param {GetBackupsResponse} [callback] The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {Backup[]} callback.backups All matching Backup instances.
* @param {object} callback.apiResponse The full API response.
* @return {void | Promise<ListBackupsResponse>}
*
* @example <caption>include:samples/api-reference-doc-snippets/backups.list.js</caption>
* region_tag:bigtable_api_list_backups
*/
getBackups(optionsOrCallback, cb) {
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
this.cluster('-').getBackups(options, callback);
}
/**
* Get Cloud Bigtable Backup instances within this instance. This returns both
* completed and pending backups as a readable stream.
*
* @param {GetBackupsOptions} [options] Configuration object. See
* {@link Instance#getBackups} for a complete list of options.
* @returns {ReadableStream<Backup>}
*
* @example
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
* const instance = bigtable.instance('my-instance');
*
* instance.getBackupsStream()
* .on('error', console.error)
* .on('data', function(backup) {
* // backup is a Backup object.
* })
* .on('end', () => {
* // All backups retrieved.
* });
*
* //-
* // If you anticipate many results, you can end a stream early to prevent
* // unnecessary processing and API requests.
* //-
* instance.getBackupsStream()
* .on('data', function(backup) {
* this.end();
* });
* ```
*/
getBackupsStream(options) {
return this.cluster('-').getBackupsStream(options);
}
/**
* Get Cluster objects for all of your clusters.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} callback The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {Cluster[]} callback.clusters List of all
* Clusters.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_get_clusters
*/
getClusters(optionsOrCallback, cb) {
const gaxOptions = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
const reqOpts = {
parent: this.name,
};
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'listClusters',
reqOpts,
gaxOpts: gaxOptions,
}, (err, resp) => {
if (err) {
callback(err);
return;
}
const clusters = resp.clusters.map(clusterObj => {
const cluster = this.cluster(clusterObj.name.split('/').pop());
cluster.metadata = clusterObj;
return cluster;
});
callback(null, clusters, resp);
});
}
/**
* @param {object} [options] Configuration object.
* @param {object} [options.gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {number} [options.requestedPolicyVersion] The policy format version
* to be returned. Valid values are 0, 1, and 3. Requests specifying an
* invalid value will be rejected. Requests for policies with any
* conditional bindings must specify version 3. Policies without any
* conditional bindings may specify any valid value or leave the field unset.
* @param {function} [callback] The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {Policy} policy The policy.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_get_instance_Iam_policy
*/
getIamPolicy(optionsOrCallback, callback) {
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
callback =
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback;
const reqOpts = {
resource: this.name,
};
if (options.requestedPolicyVersion !== null &&
options.requestedPolicyVersion !== undefined) {
reqOpts.options = {
requestedPolicyVersion: options.requestedPolicyVersion,
};
}
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'getIamPolicy',
reqOpts,
gaxOpts: options.gaxOptions,
}, (err, resp) => {
if (err) {
callback(err);
return;
}
callback(null, table_1.Table.decodePolicyEtag(resp));
});
}
/**
* Get the instance metadata.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {object} callback.metadata The metadata.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_get_instance_metadata
*/
getMetadata(optionsOrCallback, cb) {
const gaxOptions = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'getInstance',
reqOpts: {
name: this.name,
},
gaxOpts: gaxOptions,
}, (...args) => {
if (args[1]) {
this.metadata = args[1];
}
callback(...args);
});
}
/**
* Get Table objects for all the tables in your Cloud Bigtable instance.
*
* @param {object} [options] Query object.
* @param {boolean} [options.autoPaginate=true] Have pagination handled
* automatically.
* @param {object} [options.gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
* @param {number} [options.maxApiCalls] Maximum number of API calls to make.
* @param {number} [options.maxResults] Maximum number of items to return.
* @param {string} [options.pageToken] A previously-returned page token
* representing part of a larger set of results to view.
* @param {string} [options.view] View over the table's fields. Possible options
* are 'name', 'schema' or 'full'. Default: 'name'.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this request.
* @param {Table[]} callback.tables List of all Table objects.These objects contains
* only table name & id but is not a complete representation of a table.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_get_tables
*/
getTables(optionsOrCallback, cb) {
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
const gaxOpts = extend(true, {}, options.gaxOptions);
let reqOpts = Object.assign({}, options, {
parent: this.name,
view: table_1.Table.VIEWS[options.view || 'unspecified'],
});
// Copy over pageSize and pageToken values from gaxOptions.
// However values set on options take precedence.
if (gaxOpts) {
reqOpts = extend({}, {
pageSize: gaxOpts.pageSize,
pageToken: gaxOpts.pageToken,
}, reqOpts);
delete gaxOpts.pageSize;
delete gaxOpts.pageToken;
}
delete reqOpts.gaxOptions;
this.bigtable.request({
client: 'BigtableTableAdminClient',
method: 'listTables',
reqOpts,
gaxOpts,
}, (...args) => {
if (args[1]) {
args[1] = args[1].map(tableObj => {
const table = this.table(tableObj.name.split('/').pop());
table.metadata = tableObj;
return table;
});
}
callback(...args);
});
}
/**
* Get {@link Table} objects for all the tables in your Cloud Bigtable
* instance as a readable object stream.
*
* @param {object} [options] Query object. See
* {@link Instance#getTables} for a complete list of options.
* @returns {stream}
*
* @example
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
* const instance = bigtable.instance('my-instance');
*
* instance.getTablesStream()
* .on('error', console.error)
* .on('data', function(table) {
* // table is a Table object.
* })
* .on('end', () => {
* // All tables retrieved.
* });
*
* //-
* // If you anticipate many results, you can end a stream early to prevent
* // unnecessary processing and API requests.
* //-
* instance.getTablesStream()
* .on('data', function(table) {
* this.end();
* });
* ```
*/
getTablesStream(options = {}) {
const gaxOpts = extend(true, {}, options.gaxOptions);
let reqOpts = Object.assign({}, options, {
parent: this.name,
view: table_1.Table.VIEWS[options.view || 'unspecified'],
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete reqOpts.gaxOptions;
// Copy over pageSize and pageToken values from gaxOptions.
// However values set on options take precedence.
if (gaxOpts) {
reqOpts = extend({}, {
pageSize: gaxOpts.pageSize,
pageToken: gaxOpts.pageToken,
}, reqOpts);
delete gaxOpts.pageSize;
delete gaxOpts.pageToken;
}
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
const transformToTable = (chunk, enc, callback) => {
const table = self.table(chunk.name.split('/').pop());
table.metadata = chunk;
callback(null, table);
};
return pumpify.obj([
this.bigtable.request({
client: 'BigtableTableAdminClient',
method: 'listTablesStream',
reqOpts,
gaxOpts,
}),
new stream_1.Transform({ objectMode: true, transform: transformToTable }),
]);
}
/**
* Create a new table by restoring from a completed backup.
*
* The new table must be in the same instance as the instance containing
* the backup. The returned table
* {@link google.longrunning.Operation|long-running operation} can be used
* to track the progress of the operation, and to cancel it.
*
* @param {CreateTableFromBackupConfig} config Configuration object.
* @param {Backup | string} config.backup The name of the backup from which to
* restore of the form
* `projects/<project>/instances/<instance>/clusters/<cluster>/backups/<backup>`,
* or a Backup instance.
* @param {string} config.table The id of the table to create and restore to.
* @param {CallOptions} [config.gaxOptions] Request configuration options,
* outlined here:
* https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {RestoreTableCallback} [cb]
* @return {void | Promise<RestoreTableResponse>}
*
* @example <caption>include:samples/api-reference-doc-snippets/backups.restore.js</caption>
* region_tag:bigtable_api_restore_backup
*/
createTableFromBackup(config, callback) {
if (!config.table) {
throw new Error('A table id is required to restore from a backup.');
}
let backup;
if (config.backup instanceof backup_1.Backup) {
backup = config.backup;
}
else {
try {
const clusterId = config.backup.match(/clusters\/([^/]+)/)[1];
const instanceId = config.backup.match(/instances\/([^/]+)/)[1];
if (instanceId !== this.id) {
backup = this.bigtable
.instance(instanceId)
.cluster(clusterId)
.backup(config.backup);
}
else {
backup = this.cluster(clusterId).backup(config.backup);
}
}
catch (e) {
throw new Error('A complete backup name (path) is required or a Backup object.');
}
}
backup.restoreTo({ tableId: config.table, instance: this, gaxOptions: config.gaxOptions }, callback);
}
/**
* @param {object} [gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} [callback] The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {Policy} policy The policy.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_set_instance_Iam_policy
*/
setIamPolicy(policy, gaxOptionsOrCallback, callback) {
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
callback =
typeof gaxOptionsOrCallback === 'function'
? gaxOptionsOrCallback
: callback;
if (policy.etag !== null && policy.etag !== undefined) {
policy.etag = Buffer.from(policy.etag);
}
const reqOpts = {
resource: this.name,
policy,
};
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'setIamPolicy',
reqOpts,
gaxOpts: gaxOptions,
}, (err, resp) => {
if (err) {
callback(err);
}
callback(null, table_1.Table.decodePolicyEtag(resp));
});
}
/**
* Set the instance metadata.
*
* @param {object} metadata Metadata object.
* @param {string} metadata.displayName The descriptive name for this
* instance as it appears in UIs. It can be changed at any time, but
* should be kept globally unique to avoid confusion.
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this
* request.
* @param {object} callback.apiResponse The full API response.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_set_meta_data
*/
setMetadata(metadata, optionsOrCallback, cb) {
const gaxOptions = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
const reqOpts = {
instance: Object.assign({ name: this.name }, metadata),
updateMask: {
paths: [],
},
};
const fieldsForMask = ['displayName', 'type', 'labels'];
fieldsForMask.forEach(field => {
if (field in reqOpts.instance) {
reqOpts.updateMask.paths.push(snakeCase(field));
}
});
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'partialUpdateInstance',
reqOpts,
gaxOpts: gaxOptions,
}, (...args) => {
if (args[1]) {
this.metadata = args[1];
}
callback(...args);
});
}
/**
* Get a reference to a Bigtable table.
*
* @param {string} id Unique identifier of the table.
* @returns {Table}
*
* @example
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
* const instance = bigtable.instance('my-instance');
* const table = instance.table('presidents');
* ```
*/
table(id) {
return new table_1.Table(this, id);
}
/**
*
* @param {string | string[]} permissions The permission(s) to test for.
* @param {object} [gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} [callback] The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {string[]} permissions A subset of permissions that the caller is
* allowed.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_test_instance_Iam_permissions
*/
testIamPermissions(permissions, gaxOptionsOrCallback, callback) {
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
callback =
typeof gaxOptionsOrCallback === 'function'
? gaxOptionsOrCallback
: callback;
const reqOpts = {
resource: this.name,
permissions: arrify(permissions),
};
this.bigtable.request({
client: 'BigtableInstanceAdminClient',
method: 'testIamPermissions',
reqOpts,
gaxOpts: gaxOptions,
}, (err, resp) => {
if (err) {
callback(err);
return;
}
callback(null, resp.permissions);
});
}
/**
* Gets an Authorized View object for making authorized view grpc calls.
*
* @param {string} tableName The name for the Table
* @param {string} viewName The name for the Authorized view
*/
view(tableName, viewName) {
return new authorized_view_1.AuthorizedView(this, tableName, viewName);
}
/**
* Prepare an SQL query to be executed on an instance.
*
* @param {?string} [query] PreparedStatement object representing a query
* to execute.
* @param {string} [opts.query] Query string for which we want to construct the preparedStatement object.
* @param {object} [opts.parameterTypes] Object mapping names of parameters to their types.
* Type hints should be constructed using factory functions such as {@link Int64}
* @param {CallOptions} [opts.retryOptions] gax's CallOptions wich are passed straight to gax.
* The same retry options are also used when automatically refreshing the PreparedStatement.
*
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this request.
* @param {?PreparedStatement} callback.preparedStatement The preparedStatement object used to perform the executeQuery operation.
*
*/
prepareStatement(queryOrOpts, callback) {
const opts = typeof queryOrOpts === 'string' ? { query: queryOrOpts } : queryOrOpts;
const protoParamTypes = (0, parameterparsing_1.parseParameterTypes)(opts.parameterTypes || {});
const request = {
client: 'BigtableClient',
method: 'prepareQuery',
reqOpts: {
instanceName: this.name,
appProfileId: this.bigtable.appProfileId,
query: opts.query,
paramTypes: protoParamTypes,
},
gaxOpts: opts.retryOptions,
};
this.bigtable.request(request, (...args) => {
if (args[0]) {
callback(args[0]);
}
try {
callback(null, new preparedstatement_1.PreparedStatement(this.bigtable, args[1], request, opts.parameterTypes || {}));
}
catch (err) {
callback(err, undefined);
}
});
}
/**
* Execute a SQL query on an instance.
*
*
* @param {?PreparedStatement} [preparedStatement] PreparedStatement object representing a query
* to execute.
* @param {?object} [options] Configuration object. See
* {@link Instance#createExecuteQueryStream} for a complete list of options.
*
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this request.
* @param {?QueryResultRow[]} callback.rows List of rows.
* @param {?SqlTypes.ResultSetMetadata} callback.metadata Metadata for the response.
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_execute_query
*/
executeQuery(preparedStatementOrOpts, callback) {
let opts;
if (preparedStatementOrOpts instanceof preparedstatement_1.PreparedStatement) {
opts = { preparedStatement: preparedStatementOrOpts };
}
else {
opts = preparedStatementOrOpts;
}
const stream = this.createExecuteQueryStream(opts);
stream.on('error', callback).pipe(concat((rows) => {
callback(null, rows);
}));
}
/**
* Execute a SQL query on an instance.
*
* @param {PreparedStatement} [preparedStatement] SQL query to execute. Parameters can be specified using @name notation.
* @param {object} [opts] Configuration object.
* @param {object} [opts.parameters] Object mapping names of parameters used in the query to JS values.
* @param {object} [opts.retryOptions] Retry options used for executing the query. Note that the only values
* used are:
* - retryOptions.retry.retryCodes
* - retryOptions.retry.backoffSettings.maxRetries
* - retryOptions.retry.backoffSettings.totalTimeoutMillis
* - retryOptions.retry.backoffSettings.maxRetryDelayMillis
* - retryOptions.retry.backoffSettings.retryDelayMultiplier
* - retryOptions.retry.backoffSettings.initialRetryDelayMillis
* @returns {ExecuteQueryStreamWithMetadata}
*
* @example <caption>include:samples/api-reference-doc-snippets/instance.js</caption>
* region_tag:bigtable_api_create_query_stream
*/
createExecuteQueryStream(opts) {
/**
* We create the following streams:
* responseStream -> byteBuffer -> readerStream -> resultStream
*
* The last two (readerStream and resultStream) are connected using pumpify
* and returned to the caller.
*
* When a request is made responseStream and byteBuffer are created,
* connected using pumpify and piped to the readerStream.
*
* On retry, the old responseStream-byteBuffer pair is discarded and a
* new pair is crated.
*
* For more info please refer to comments in setupRetries function.
*
*/
const metadataConsumer = new metadataconsumer_1.MetadataConsumer();
let callerCancelled = false;
const setCallerCancelled = (value) => {
callerCancelled = value;
};
const hasCallerCancelled = () => callerCancelled;
const resultStream = new queryresultrowtransformer_1.ExecuteQueryStreamTransformWithMetadata(metadataConsumer, hasCallerCancelled, opts.encoding);
const protoParams = (0, parameterparsing_1.parseParameters)(opts.parameters || {}, opts.preparedStatement.getParameterTypes());
const readerStream = new protobufreadertransformer_1.ProtobufReaderTransformer(metadataConsumer);
const reqOpts = {
instanceName: this.name,
appProfileId: this.bigtable.appProfileId,
params: protoParams,
};
// This creates a row stream which is two streams connected in a series.
const callerStream = (0, executequerystatemachine_1.createCallerStream)(readerStream, resultStream, metadataConsumer, setCallerCancelled);
const stateMachine = new executequerystatemachine_1.ExecuteQueryStateMachine(this.bigtable, callerStream, opts.preparedStatement, reqOpts, opts.retryOptions?.retry, opts.encoding);
// make sure stateMachine is not garbage collected as long as the callerStream.
callerStream._stateMachine = stateMachine;
return callerStream;
}
}
exports.Instance = Instance;
/*! Developer Documentation
*
* All async methods (except for streams) will return a Promise in the event
* that a callback is omitted.
*/
(0, promisify_1.promisifyAll)(Instance, {
exclude: [
'appProfile',
'cluster',
'table',
'getBackupsStream',
'getTablesStream',
'getAppProfilesStream',
'view',
],
});
/**
* Reference to the {@link Instance} class.
* @name module:@google-cloud/bigtable.Instance
* @see Instance
*/
//# sourceMappingURL=instance.js.map