@google-cloud/bigtable
Version:
Cloud Bigtable Client Library for Node.js
940 lines • 36.8 kB
JavaScript
;
// 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.SqlTypes = exports.Table = exports.PartialFailureError = exports.RowError = exports.Row = exports.Mutation = exports.Instance = exports.FilterError = exports.Filter = exports.Family = exports.FamilyError = exports.Cluster = exports.RowStateEnum = exports.ChunkTransformer = exports.Backup = exports.AppProfile = exports.protos = exports.v2 = exports.Bigtable = void 0;
const projectify_1 = require("@google-cloud/projectify");
const promisify_1 = require("@google-cloud/promisify");
const arrify = require("arrify");
const extend = require("extend");
const google_gax_1 = require("google-gax");
const gax = require("google-gax");
const protos = require("../protos/protos");
exports.protos = protos;
const SqlTypes = require("./execute-query/types");
exports.SqlTypes = SqlTypes;
const cluster_1 = require("./cluster");
const instance_1 = require("./instance");
const v2 = require("./v2");
exports.v2 = v2;
const stream_1 = require("stream");
const grpcGcpModule = require("grpc-gcp");
const cluster_2 = require("./utils/cluster");
const metrics_config_manager_1 = require("./client-side-metrics/metrics-config-manager");
const gcp_metrics_handler_1 = require("./client-side-metrics/gcp-metrics-handler");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const streamEvents = require('stream-events');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const PKG = require('../../package.json');
const { grpc } = new gax.GrpcClient();
// Enable channel pooling
const grpcGcp = grpcGcpModule(google_gax_1.grpc);
/**
* Retrieves the universe domain, if configured.
*
* This function checks for a universe domain in the following order:
* 1. The `universeDomain` property within the provided options.
* 2. The `universeDomain` or `universe_domain` property within the `opts` object.
* 3. The `GOOGLE_CLOUD_UNIVERSE_DOMAIN` environment variable.
*
* If a universe domain is found in any of these locations, it is returned.
* Otherwise, the function returns `undefined`.
*
* @param {BigtableOptions} options - The Bigtable client options.
* @param {gax.ClientOptions} [gaxOpts] - Optional gax client options.
* @returns {string | undefined} The universe domain, or `undefined` if not found.
*/
function getUniverseDomainOnly(options, gaxOpts) {
// From https://github.com/googleapis/nodejs-bigtable/blob/589540475b0b2a055018a1cb6e475800fdd46a37/src/v2/bigtable_client.ts#L120-L128.
// This code for universe domain was taken from the Gapic Layer.
// It is reused here to build the service path.
const universeDomainEnvVar = typeof process === 'object' && typeof process.env === 'object'
? process.env['GOOGLE_CLOUD_UNIVERSE_DOMAIN']
: undefined;
return (gaxOpts?.universeDomain ??
gaxOpts?.universe_domain ??
options?.universeDomain ??
universeDomainEnvVar);
}
/**
* Retrieves the universe domain options from the provided options.
*
* This function examines the provided BigtableOptions and an optional
* gax.ClientOptions object to determine the universe domain to be used.
* It prioritizes the `universeDomain` property in the options, then checks
* for `universeDomain` or `universe_domain` in the gax options, and finally
* falls back to the `GOOGLE_CLOUD_UNIVERSE_DOMAIN` environment variable.
* If a universe domain is found, it returns an object containing the
* `universeDomain` property; otherwise, it returns `null`.
*
* @param {BigtableOptions} options - The Bigtable client options.
* @param {gax.ClientOptions} [gaxOpts] - Optional gax client options.
* @returns {{universeDomain: string} | null} An object containing the `universeDomain` property if found,
* otherwise `null`.
*/
function getUniverseDomainOptions(options, gaxOpts) {
const universeDomainOnly = getUniverseDomainOnly(options, gaxOpts);
return universeDomainOnly ? { universeDomain: universeDomainOnly } : null;
}
/**
* Retrieves the domain to be used for the service path.
*
* This function retrieves the domain from gax.ClientOptions passed in or via an environment variable.
* It defaults to 'googleapis.com' if none has been set.
* @param {string} [prefix] The prefix for the domain.
* @param {BigtableOptions} [options] The options passed into the Bigtable client.
* @param {gax.ClientOptions} [gaxOpts] The gax client options.
* @returns {string} The universe domain.
*/
function getDomain(prefix, options, gaxOpts) {
const universeDomainOnly = getUniverseDomainOnly(options, gaxOpts);
const suffix = universeDomainOnly ? universeDomainOnly : 'googleapis.com';
return `${prefix}.${suffix}`;
}
/**
* @typedef {object} ClientConfig
* @property {string} [apiEndpoint] Override the default API endpoint used
* to reach Bigtable. This is useful for connecting to your local Bigtable
* emulator.
* @property {string} [projectId] The project ID from the Google Developer's
* Console, e.g. 'grape-spaceship-123'. We will also check the environment
* variable `GCLOUD_PROJECT` for your project ID. If your app is running in
* an environment which supports {@link
* https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application
* Application Default Credentials}, your project ID will be detected
* automatically.
* @property {string} [keyFilename] Full path to the a .json, .pem, or .p12 key
* downloaded from the Google Developers Console. If you provide a path to a
* JSON file, the `projectId` option above is not necessary. NOTE: .pem and
* .p12 require you to specify the `email` option as well.
* @property {string} [appProfileId] An application profile ID, a configuration
* string value describing how Cloud Bigtable should treat traffic from a
* particular end user application.
* @property {string} [email] Account email address. Required when using a .pem
* or .p12 keyFilename.
* @property {object} [credentials] Credentials object.
* @property {string} [credentials.client_email]
* @property {string} [credentials.private_key]
* @property {boolean} [autoRetry=true] Automatically retry requests if the
* response is related to rate limits or certain intermittent server errors.
* We will exponentially backoff subsequent requests by default.
* @property {number} [maxRetries=3] Maximum number of automatic retries
* attempted before returning the error.
*/
/**
* @see [Creating a Cloud Bigtable Cluster]{@link https://cloud.google.com/bigtable/docs/creating-instance}
* @see [Cloud Bigtable Concepts Overview]{@link https://cloud.google.com/bigtable/docs/concepts}
*
* @class
* @param {ClientConfig} [options] Configuration options.
*
* @example Create a client that uses <a href="https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application">Application Default Credentials (ADC)</a>:
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
*
* ```
* @example Create a client with <a href="https://cloud.google.com/docs/authentication/production#obtaining_and_providing_service_account_credentials_manually">explicit credentials</a>:
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable({
* projectId: 'your-project-id',
* keyFilename: '/path/to/keyfile.json'
* });
*
* ```
* @example The Bigtable Emulator
* ```
* // Make sure you have the {@link https://cloud.google.com/sdk/downloads gcloud SDK installed}, then run:
* $ gcloud beta emulators bigtable start
*
* // Before running your Node.js app, set the environment variables that this
* // library will look for to connect to the emulator:
*
* $ $(gcloud beta emulators bigtable env-init)
*
* ```
* @example Creating a Bigtable Instance and Cluster
* ```
*
* // Before you create your table, you first need to create a Bigtable Instance
* // and cluster for the table to be served from.
*
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
*
* const callback = (err, instance, operation) => {
* operation
* .on('error', console.log)
* .on('complete', () => {
* // `instance` is your newly created Instance object.
* });
* };
*
* const instance = bigtable.instance('my-instance');
*
* instance.create({
* clusters: [
* {
* id: 'my-cluster',
* location: 'us-central1-b',
* nodes: 3
* }
* ]
* }, callback);
*
* // This can also be done from either the Google Cloud Platform Console or the
* // `gcloud` cli tool. Please refer to the
* // {@link https://cloud.google.com/bigtable/docs/creating-instance official Bigtable documentation}
* // for more information.
*
* ```
* @example Creating Tables
* ```
* // After creating your instance and enabling the Bigtable APIs, you are now
* // ready to create your table with {@link Instance#createTable}.
* instance.createTable('prezzy', function(err, table) {
* // `table` is your newly created Table object.
* });
*
* ```
* @example Creating Column Families
* ```
* // Column families are used to group together various pieces of data within
* // your table. You can think of column families as a mechanism to categorize
* // all of your data.
* //
* // We can create a column family with {@link Table#createFamily}.
* const table = instance.table('prezzy');
*
* table.createFamily('follows', function(err, family) {
* // `family` is your newly created Family object.
* });
*
* // It is also possible to create your column families when creating a new
* // table.
* const options = {
* families: ['follows']
* };
*
* instance.createTable('prezzy', options, function(err, table) {});
*
* ```
* @example Creating Rows
* ```
* // New rows can be created within your table using
* // {@link Table#insert}. You must provide a unique key for each row
* // to be inserted, this key can then be used to retrieve your row at a later
* // time.
* //
* // With Bigtable, all columns have a unique id composed of a column family
* // and a column qualifier. In the example below `follows` is the column
* // family and `tjefferson` is the column qualifier. Together they could be
* // referred to as `follows:tjefferson`.
* const rows = [
* {
* key: 'wmckinley',
* data: {
* follows: {
* tjefferson: 1
* }
* }
* }
* ];
*
* table.insert(rows, err => {
* if (!err) {
* // Your rows were successfully inserted.
* }
* });
*
* ```
* @example Retrieving Rows
* ```
* // If you're anticipating a large number of rows to be returned, we suggest
* // using the {@link Table#getRows} streaming API.
* table.createReadStream()
* .on('error', console.error)
* .on('data', row => {
* // `row` is a Row object.
* });
*
* // If you're not anticpating a large number of results, a callback mode
* // is also available.
* const callback = (err, rows) => {
* // `rows` is an array of Row objects.
* };
*
* table.getRows(callback);
*
* // A range of rows can be retrieved by providing `start` and `end` row keys.
* const options = {
* start: 'gwashington',
* end: 'wmckinley'
* };
*
* table.getRows(options, callback);
*
* // Retrieve an individual row with {@link Row#get}.
* const row = table.row('alincoln');
*
* row.get(err => {
* // `row.data` is now populated.
* });
*
* ```
* @example Accessing Row Data
* ```
* // When retrieving rows, upon success the `row.data` property will be
* // populated by an object. That object will contain additional objects
* // for each family in your table that the row has data for.
* //
* // By default, when retrieving rows, each column qualifier will provide you
* // with all previous versions of the data. So your `row.data` object could
* // resemble the following.
* {
* follows: {
* wmckinley: [
* {
* value: 1,
* timestamp: 1466017315951
* }, {
* value: 2,
* timestamp: 1458619200000
* }
* ]
* }
* }
*
* // The `timestamp` field can be used to order cells from newest to oldest.
* // If you only wish to retrieve the most recent version of the data, you
* // can specify the number of cells with a {@link Filter} object.
* const filter = [
* {
* column: {
* cellLimit: 1
* }
* }
* ];
*
* table.getRows({
* filter: filter
* }, callback);
*
* ```
* @example Deleting Row Data
* ```
* // We can delete all of an individual row's cells using {@link Row#delete}.
* const callback = err => {
* if (!err) {
* // All cells for this row were deleted successfully.
* }
* };
*
* row.delete(callback);
*
* // To delete a specific set of cells, we can provide an array of
* // column families and qualifiers.
* const cells = [
* 'follows:gwashington',
* 'traits'
* ];
*
* row.delete(cells, callback);
*
* ```
* @example Deleting Rows
* ```
* // If you wish to delete multiple rows entirely, we can do so with
* // {@link Table#deleteRows}. You can provide this method with a
* // row key prefix.
* const options = {
* prefix: 'gwash'
* };
*
* table.deleteRows(options, err => {
* if (!err) {
* // Rows were deleted successfully.
* }
* });
*
* // If you omit the prefix, you can delete all rows in your table.
* table.deleteRows(err => {
* if (!err) {
* // All rows were deleted successfully.
* }
* });
* ```
*/
class Bigtable {
customEndpoint;
options;
api;
auth;
projectId;
appProfileId;
projectName;
shouldReplaceProjectIdToken;
static AppProfile;
static Instance;
static Cluster;
_metricsConfigManager;
constructor(options = {}) {
// Determine what scopes are needed.
// It is the union of the scopes on all three clients.
const scopes = [];
const clientClasses = [
v2.BigtableClient,
v2.BigtableInstanceAdminClient,
v2.BigtableTableAdminClient,
];
for (const clientClass of clientClasses) {
for (const scope of clientClass.scopes) {
if (!scopes.includes(scope)) {
scopes.push(scope);
}
}
}
const customEndpoint = options.apiEndpoint || process.env.BIGTABLE_EMULATOR_HOST;
this.customEndpoint = customEndpoint;
let customEndpointBaseUrl;
let customEndpointPort;
let sslCreds;
if (customEndpoint) {
const customEndpointParts = customEndpoint.split(':');
customEndpointBaseUrl = customEndpointParts[0];
customEndpointPort = Number(customEndpointParts[1]);
sslCreds = grpc.credentials.createInsecure();
}
const baseOptions = Object.assign({
libName: 'gccl',
libVersion: PKG.version,
port: customEndpointPort || 443,
sslCreds,
scopes,
'grpc.keepalive_time_ms': 30000,
'grpc.keepalive_timeout_ms': 10000,
});
const dataOptions = Object.assign({}, baseOptions, getUniverseDomainOptions(options, options.BigtableClient), {
servicePath: customEndpointBaseUrl ||
getDomain('bigtable', options, options.BigtableClient),
'grpc.callInvocationTransformer': grpcGcp.gcpCallInvocationTransformer,
'grpc.channelFactoryOverride': grpcGcp.gcpChannelFactoryOverride,
'grpc.gcpApiConfig': grpcGcp.createGcpApiConfig({
channelPool: {
minSize: 2,
maxSize: 4,
maxConcurrentStreamsLowWatermark: 10,
debugHeaderIntervalSecs: 600,
},
}),
}, options);
const adminOptions = Object.assign({}, baseOptions, getUniverseDomainOptions(options, options.BigtableTableAdminClient), {
servicePath: customEndpointBaseUrl ||
getDomain('bigtableadmin', options, options.BigtableTableAdminClient),
}, options);
const instanceAdminOptions = Object.assign({}, baseOptions, getUniverseDomainOptions(options, options.BigtableInstanceAdminClient), {
servicePath: customEndpointBaseUrl ||
getDomain('bigtableadmin', options, options.BigtableInstanceAdminClient),
}, options);
this.options = {
BigtableClient: dataOptions,
BigtableInstanceAdminClient: instanceAdminOptions,
BigtableTableAdminClient: adminOptions,
};
this.api = {};
this.auth = new google_gax_1.GoogleAuth(Object.assign({}, baseOptions, options));
this.projectId = options.projectId || '{{projectId}}';
this.appProfileId = options.appProfileId;
this.projectName = `projects/${this.projectId}`;
this.shouldReplaceProjectIdToken = this.projectId === '{{projectId}}';
const handlers = options.metricsEnabled === true
? [new gcp_metrics_handler_1.GCPMetricsHandler(options)]
: [];
this._metricsConfigManager = new metrics_config_manager_1.ClientSideMetricsConfigManager(handlers);
}
/**
* Create a Cloud Bigtable instance.
*
* @see [Creating a Cloud Bigtable Instance]{@link https://cloud.google.com/bigtable/docs/creating-instance}
*
* @param {string} id The unique id of the instance.
* @param {object} options Instance creation options.
* @param {object[]} options.clusters The clusters to be created within the
* instance.
* @param {string} [options.displayName] The descriptive name for this instance
* as it appears in UIs.
* @param {Object.<string, string>} [options.labels] Labels are a flexible and
* lightweight mechanism for organizing cloud resources into groups that
* reflect a customer's organizational needs and deployment strategies.
* They can be used to filter resources and aggregate metrics.
*
* * Label keys must be between 1 and 63 characters long and must conform to
* the regular expression: `[\p{Ll}\p{Lo}][\p{Ll}\p{Lo}\p{N}_-]{0,62}`.
* * Label values must be between 0 and 63 characters long and must conform
* to the regular expression: `[\p{Ll}\p{Lo}\p{N}_-]{0,63}`.
* * No more than 64 labels can be associated with a given resource.
* * Keys and values must both be under 128 bytes.
* @param {string} [options.type] The type of the instance. Options are
* 'production' or 'development'.
* @param {object} [options.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 {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
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
*
* const callback = function(err, instance, operation, apiResponse) {
* if (err) {
* // Error handling omitted.
* }
*
* operation
* .on('error', console.log)
* .on('complete', () => {
* // The instance was created successfully.
* });
* };
*
* const options = {
* displayName: 'my-sweet-instance',
* labels: {env: 'prod'},
* clusters: [
* {
* id: 'my-sweet-cluster',
* nodes: 3,
* location: 'us-central1-b',
* storage: 'ssd'
* }
* ]
* };
*
* bigtable.createInstance('my-instance', options, callback);
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bigtable.createInstance('my-instance', options).then(function(data) {
* const instance = data[0];
* const operation = data[1];
* const apiResponse = data[2];
* });
* ```
*/
createInstance(id, options, callback) {
if (typeof options !== 'object') {
throw new Error('A configuration object is required to create an instance.');
}
if (!options.clusters) {
throw new Error('At least one cluster configuration object is required to create an instance.');
}
const reqOpts = {
parent: this.projectName,
instanceId: id,
instance: {
displayName: options.displayName || id,
labels: options.labels,
},
};
if (options.type) {
reqOpts.instance.type = instance_1.Instance.getTypeType_(options.type);
}
reqOpts.clusters = arrify(options.clusters).reduce((clusters, cluster) => {
// TOD: Find a way to eliminate all ClusterInfo casts in this file.
if (!cluster.id) {
throw new Error('A cluster was provided without an `id` property defined.');
}
if (typeof cluster.key !== 'undefined' &&
typeof cluster.encryption !== 'undefined') {
throw new Error('A cluster was provided with both `encryption` and `key` defined.');
}
cluster_2.ClusterUtils.validateClusterMetadata(cluster);
clusters[cluster.id] =
cluster_2.ClusterUtils.getClusterBaseConfigWithFullLocation(cluster, this.projectId, undefined);
Object.assign(clusters[cluster.id], {
defaultStorageType: cluster_1.Cluster.getStorageType_(cluster.storage),
});
if (cluster.key) {
clusters[cluster.id].encryptionConfig = {
kmsKeyName: cluster.key,
};
}
if (cluster.encryption) {
clusters[cluster.id].encryptionConfig = cluster.encryption;
}
return clusters;
}, {});
this.request({
client: 'BigtableInstanceAdminClient',
method: 'createInstance',
reqOpts,
gaxOpts: options.gaxOptions,
}, (...args) => {
const err = args[0];
if (!err) {
args.splice(1, 0, this.instance(id));
}
callback(...args);
});
}
/**
* @typedef {array} GetInstancesResponse
* @property {Instance[]} 0 Array of {@link Instance} instances.
* @property {string[]} 1 locations from which Instance information could not be retrieved
* @property {object} 2 The full API response.
* Note: 'failedLocations' property may contain locations from which
* Instance information could not be retrieved.
* Values are of the form `projects/<project>/locations/<zone_id>`
*/
/**
* @callback GetInstancesCallback
* @param {?Error} err Request error, if any.
* @param {Instance[]} instances Array of {@link Instance} instances.
* @param {string[]} locations from which Instance information could not be retrieved
* @param {object} apiResponse The full API response.
* Note: 'failedLocations' property may contain locations from which
* Instance information could not be retrieved.
* Values are of the form `projects/<project>/locations/<zone_id>`
*/
/**
* Get Instance objects for all of your Cloud Bigtable instances.
*
* @param {object} [gaxOptions] Request configuration options, outlined here:
* https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
* @param {GetInstancesCallback} [callback] The callback function.
* @returns {Promise<GetInstancesResponse>}
*
* @example
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
* const bigtable = new Bigtable();
*
* bigtable.getInstances(function(err, instances, response) {
* if (!err) {
* // `instances` is an array of Instance objects.
* if (response.failedLocations.length > 0) {
* // These locations contain instances which could not be retrieved.
* }
* }
* });
*
* ```
* @example If the callback is omitted, we'll return a Promise.
* ```
* bigtable.getInstances().then(function(data) {
* const instances = data[0];
* const fullResponse = data[2];
*
* if (fullResponse.failedLocations.length > 0) {
* // These locations contain instances which could not be retrieved.
* const failedLocations = fullResponse.failedLocations;
* }
* });
* ```
*/
getInstances(gaxOptionsOrCallback, callback) {
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
callback =
typeof gaxOptionsOrCallback === 'function'
? gaxOptionsOrCallback
: callback;
const reqOpts = {
parent: this.projectName,
};
this.request({
client: 'BigtableInstanceAdminClient',
method: 'listInstances',
reqOpts,
gaxOpts: gaxOptions,
}, (err, resp) => {
if (err) {
callback(err);
return;
}
const instances = resp.instances.map((instanceData) => {
const instance = this.instance(instanceData.name.split('/').pop());
instance.metadata = instanceData;
return instance;
});
callback(null, instances, resp.failedLocations, resp);
});
}
/**
* Get a reference to a Cloud Bigtable instance.
*
* @param {string} id The id of the instance.
* @returns {Instance}
*/
instance(name) {
return new instance_1.Instance(this, name);
}
/**
* Funnel all API requests through this method, to be sure we have a project ID.
*
* @param {object} config Configuration object.
* @param {object} config.gaxOpts GAX options.
* @param {function} config.method The gax method to call.
* @param {object} config.reqOpts Request options.
* @param {function} [callback] Callback function.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
request(config, callback) {
const isStreamMode = !callback;
let gaxStream;
let stream;
const prepareGaxRequest = (callback) => {
this.getProjectId_((err, projectId) => {
if (err) {
callback(err);
return;
}
let gaxClient = this.api[config.client];
if (!gaxClient) {
// Lazily instantiate client.
const clientOptions = this.options[config.client];
gaxClient = new v2[config.client](clientOptions);
this.api[config.client] = gaxClient;
}
let reqOpts = extend(true, {}, config.reqOpts);
if (this.shouldReplaceProjectIdToken && projectId !== '{{projectId}}') {
reqOpts = (0, projectify_1.replaceProjectIdToken)(reqOpts, projectId);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const requestFn = gaxClient[config.method].bind(gaxClient, reqOpts, config.gaxOpts);
callback(null, requestFn);
});
};
const gapicStreamingMethods = {
listAppProfilesStream: true,
listBackupsStream: true,
listTablesStream: true,
};
if (isStreamMode) {
stream = streamEvents(new stream_1.PassThrough({ objectMode: true }));
stream.abort = () => {
if (gaxStream && gaxStream.cancel) {
gaxStream.cancel();
}
};
if (config.method in gapicStreamingMethods) {
stream.once('reading', makeGapicStreamRequest);
}
else {
stream.once('reading', makeRequestStream);
}
return stream;
}
else {
makeRequestCallback();
}
function makeRequestCallback() {
prepareGaxRequest((err, requestFn) => {
if (err) {
callback(err);
return;
}
requestFn(callback);
});
}
function makeRequestStream() {
const retryRequestOptions = Object.assign({
currentRetryAttempt: 0,
noResponseRetries: 0,
objectMode: true,
}, config.retryOpts);
config.gaxOpts = Object.assign(config.gaxOpts || {}, {
retryRequestOptions,
});
prepareGaxRequest((err, requestFn) => {
if (err) {
stream.destroy(err);
return;
}
gaxStream = requestFn();
gaxStream
.on('error', stream.destroy.bind(stream))
.on('metadata', stream.emit.bind(stream, 'metadata'))
.on('status', stream.emit.bind(stream, 'status'))
.on('request', stream.emit.bind(stream, 'request'))
.pipe(stream);
});
}
function makeGapicStreamRequest() {
prepareGaxRequest((err, requestFn) => {
if (err) {
stream.destroy(err);
return;
}
gaxStream = requestFn();
gaxStream
.on('error', (err) => {
stream.destroy(err);
})
.on('metadata', metadata => {
stream.emit('metadata', metadata);
})
.on('response', response => {
stream.emit('response', response);
})
.pipe(stream);
});
}
}
/**
* Close all bigtable clients. New requests will be rejected but it will not
* kill connections with pending requests.
*/
close() {
const combined = Object.keys(this.api).map(clientType => this.api[clientType].close());
return Promise.all(combined);
}
/**
* Determine and localize the project ID. If a user provides an ID, we bypass
* checking with the auth client for an ID.
*
* @private
*
* @param {function} callback Callback function.
* @param {?error} callback.err An error returned from the auth client.
* @param {string} callback.projectId The detected project ID.
*/
getProjectId_(callback) {
const projectIdRequired = this.projectId === '{{projectId}}' && !this.customEndpoint;
if (!projectIdRequired) {
setImmediate(callback, null, this.projectId);
return;
}
this.auth.getProjectId((err, projectId) => {
if (err) {
callback(err);
return;
}
this.projectId = projectId;
callback(null, this.projectId);
});
}
}
exports.Bigtable = Bigtable;
/*! Developer Documentation
*
* All async methods (except for streams) will return a Promise in the event
* that a callback is omitted.
*/
(0, promisify_1.promisifyAll)(Bigtable, {
exclude: ['close', 'instance', 'operation', 'request'],
});
/**
* {@link AppProfile} class.
*
* @name Bigtable.AppProfile
* @see AppProfile
* @type {Constructor}
*/
/**
* {@link Cluster} class.
*
* @name Bigtable.Cluster
* @see Cluster
* @type {Constructor}
*/
/**
* {@link Instance} class.
*
* @name Bigtable.Instance
* @see Instance
* @type {Constructor}
*/
// Allow creating a `Bigtable` instance without using the `new` keyword.
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-class-assign
Bigtable = new Proxy(Bigtable, {
apply(target, thisArg, argumentsList) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return new target(...argumentsList);
},
});
/**
* The default export of the `@google-cloud/bigtable` package is the
* {@link Bigtable} class.
*
* See {@link Bigtable} and {@link ClientConfig} for client methods and
* configuration options.
*
* @module {constructor} @google-cloud/bigtable
* @alias nodejs-bigtable
*
* @example Install the client library with <a href="https://www.npmjs.com/">npm</a>:
* ```
* npm install --save @google-cloud/bigtable
*
* ```
* @example Import the client library
* ```
* const {Bigtable} = require('@google-cloud/bigtable');
*
* ```
* @example Create a client that uses <a href="https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application">Application Default Credentials (ADC)</a>:
* ```
* const bigtable = new Bigtable();
*
* ```
* @example Create a client with <a href="https://cloud.google.com/docs/authentication/production#obtaining_and_providing_service_account_credentials_manually">explicit credentials</a>:
* ```
* const bigtable = new Bigtable({
* projectId: 'your-project-id',
* keyFilename: '/path/to/keyfile.json'
* });
*
* ```
* @example <caption>include:samples/quickstart.js</caption>
* region_tag:bigtable_quickstart
* Full quickstart example:
*/
module.exports = Bigtable;
module.exports.v2 = v2;
module.exports.Bigtable = Bigtable;
module.exports.SqlTypes = SqlTypes;
var app_profile_1 = require("./app-profile");
Object.defineProperty(exports, "AppProfile", { enumerable: true, get: function () { return app_profile_1.AppProfile; } });
var backup_1 = require("./backup");
Object.defineProperty(exports, "Backup", { enumerable: true, get: function () { return backup_1.Backup; } });
var chunktransformer_1 = require("./chunktransformer");
Object.defineProperty(exports, "ChunkTransformer", { enumerable: true, get: function () { return chunktransformer_1.ChunkTransformer; } });
Object.defineProperty(exports, "RowStateEnum", { enumerable: true, get: function () { return chunktransformer_1.RowStateEnum; } });
var cluster_3 = require("./cluster");
Object.defineProperty(exports, "Cluster", { enumerable: true, get: function () { return cluster_3.Cluster; } });
var family_1 = require("./family");
Object.defineProperty(exports, "FamilyError", { enumerable: true, get: function () { return family_1.FamilyError; } });
Object.defineProperty(exports, "Family", { enumerable: true, get: function () { return family_1.Family; } });
var filter_1 = require("./filter");
Object.defineProperty(exports, "Filter", { enumerable: true, get: function () { return filter_1.Filter; } });
Object.defineProperty(exports, "FilterError", { enumerable: true, get: function () { return filter_1.FilterError; } });
var instance_2 = require("./instance");
Object.defineProperty(exports, "Instance", { enumerable: true, get: function () { return instance_2.Instance; } });
var mutation_1 = require("./mutation");
Object.defineProperty(exports, "Mutation", { enumerable: true, get: function () { return mutation_1.Mutation; } });
var row_1 = require("./row");
Object.defineProperty(exports, "Row", { enumerable: true, get: function () { return row_1.Row; } });
Object.defineProperty(exports, "RowError", { enumerable: true, get: function () { return row_1.RowError; } });
var table_1 = require("./table");
Object.defineProperty(exports, "PartialFailureError", { enumerable: true, get: function () { return table_1.PartialFailureError; } });
Object.defineProperty(exports, "Table", { enumerable: true, get: function () { return table_1.Table; } });
//# sourceMappingURL=index.js.map