UNPKG

@google-cloud/bigtable

Version:
1,186 lines 48.7 kB
"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