1 5
/*!
2 5
 * Copyright 2016 Google Inc. All Rights Reserved.
3 5
 *
4 5
 * Licensed under the Apache License, Version 2.0 (the "License");
5 5
 * you may not use this file except in compliance with the License.
6 5
 * You may obtain a copy of the License at
7 5
 *
8 5
 *      http://www.apache.org/licenses/LICENSE-2.0
9 5
 *
10 5
 * Unless required by applicable law or agreed to in writing, software
11 5
 * distributed under the License is distributed on an "AS IS" BASIS,
12 5
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 5
 * See the License for the specific language governing permissions and
14 5
 * limitations under the License.
15 5
 */
16 5

17 5
import arrify = require('arrify');
18 5
import {ServiceObjectConfig, GetConfig} from '@google-cloud/common';
19 5
// eslint-disable-next-line @typescript-eslint/no-var-requires
20 5
const common = require('./common-grpc/service-object');
21 5
import {promisifyAll} from '@google-cloud/promisify';
22 5
import * as extend from 'extend';
23 5
import snakeCase = require('lodash.snakecase');
24 5
import {Database, SessionPoolConstructor} from './database';
25 5
import {Spanner, RequestConfig} from '.';
26 5
import {
27 5
  RequestCallback,
28 5
  PagedOptions,
29 5
  PagedResponse,
30 5
  LongRunningCallback,
31 5
  NormalCallback,
32 5
  ResourceCallback,
33 5
  PagedOptionsWithFilter,
34 5
  CLOUD_RESOURCE_HEADER,
35 5
} from './common';
36 5
import {Duplex} from 'stream';
37 5
import {SessionPoolOptions, SessionPool} from './session-pool';
38 5
import {grpc, Operation as GaxOperation, CallOptions} from 'google-gax';
39 5
import {Backup} from './backup';
40 5
import {google as instanceAdmin} from '../protos/protos';
41 5
import {google as databaseAdmin} from '../protos/protos';
42 5
import {google as spannerClient} from '../protos/protos';
43 5
import {CreateInstanceRequest} from './index';
44 5

45 5
export type IBackup = databaseAdmin.spanner.admin.database.v1.IBackup;
46 5
export type IDatabase = databaseAdmin.spanner.admin.database.v1.IDatabase;
47 5
export type IInstance = instanceAdmin.spanner.admin.instance.v1.IInstance;
48 5
export type IOperation = instanceAdmin.longrunning.IOperation;
49 5
export type CreateInstanceResponse = [Instance, GaxOperation, IOperation];
50 5
export type CreateDatabaseResponse = [Database, GaxOperation, IOperation];
51 5
export type DeleteInstanceResponse = [instanceAdmin.protobuf.IEmpty];
52 5
export type ExistsInstanceResponse = [boolean];
53 5
export type GetInstanceResponse = [Instance, IInstance];
54 5
export type GetInstanceMetadataResponse = [IInstance];
55 5
export interface GetInstanceMetadataOptions {
56 5
  fieldNames?: string | string[];
57 5
  gaxOptions?: CallOptions;
58 5
}
59 5
export type GetDatabasesResponse = PagedResponse<
60 5
  Database,
61 5
  databaseAdmin.spanner.admin.database.v1.IListDatabasesResponse
62 5
>;
63 5
export type SetInstanceMetadataResponse = [GaxOperation, IOperation];
64 5
export type GetBackupsResponse = PagedResponse<
65 5
  Backup,
66 5
  databaseAdmin.spanner.admin.database.v1.IListBackupsResponse
67 5
>;
68 5
export type GetBackupOperationsResponse = PagedResponse<
69 5
  IOperation,
70 5
  databaseAdmin.spanner.admin.database.v1.IListBackupOperationsResponse
71 5
>;
72 5
export type GetDatabaseOperationsResponse = PagedResponse<
73 5
  IOperation,
74 5
  databaseAdmin.spanner.admin.database.v1.IListDatabaseOperationsResponse
75 5
>;
76 5

77 5
export interface CreateDatabaseOptions
78 5
  extends databaseAdmin.spanner.admin.database.v1.ICreateDatabaseRequest {
79 5
  poolOptions?: SessionPoolOptions;
80 5
  poolCtor?: SessionPool;
81 5
  schema?: string;
82 5
  gaxOptions?: CallOptions;
83 5
}
84 5
export type GetDatabasesOptions = PagedOptions;
85 5
export type CreateInstanceCallback = LongRunningCallback<Instance>;
86 5
export type CreateDatabaseCallback = LongRunningCallback<Database>;
87 5
export type DeleteInstanceCallback = NormalCallback<instanceAdmin.protobuf.IEmpty>;
88 5

89 5
export type ExistsInstanceCallback = NormalCallback<boolean>;
90 5
export type GetDatabasesCallback = RequestCallback<
91 5
  Database,
92 5
  databaseAdmin.spanner.admin.database.v1.IListDatabasesResponse
93 5
>;
94 5
export type GetInstanceCallback = ResourceCallback<Instance, IInstance>;
95 5
export type GetInstanceMetadataCallback = NormalCallback<IInstance>;
96 5
export type SetInstanceMetadataCallback = ResourceCallback<
97 5
  GaxOperation,
98 5
  IOperation
99 5
>;
100 5
export type GetBackupsOptions = PagedOptionsWithFilter;
101 5

102 5
export type GetBackupsCallback = RequestCallback<
103 5
  Backup,
104 5
  databaseAdmin.spanner.admin.database.v1.IListBackupsResponse
105 5
>;
106 5
export type GetBackupOperationsOptions = PagedOptionsWithFilter;
107 5

108 5
export type GetBackupOperationsCallback = RequestCallback<
109 5
  IOperation,
110 5
  databaseAdmin.spanner.admin.database.v1.IListBackupOperationsResponse
111 5
>;
112 5
export type GetDatabaseOperationsOptions = PagedOptionsWithFilter;
113 5

114 5
export type GetDatabaseOperationsCallback = RequestCallback<
115 5
  IOperation,
116 5
  databaseAdmin.spanner.admin.database.v1.IListDatabaseOperationsResponse
117 5
>;
118 5
export interface GetInstanceConfig
119 5
  extends GetConfig,
120 5
    CreateInstanceRequest,
121 5
    GetInstanceMetadataOptions {}
122 5

123 5
interface InstanceRequest {
124 5
  (
125 5
    config: RequestConfig,
126 5
    callback: ResourceCallback<GaxOperation, IOperation>
127 5
  ): void;
128 5
  <T>(config: RequestConfig, callback: RequestCallback<T>): void;
129 5
  <T, R>(config: RequestConfig, callback: RequestCallback<T, R>): void;
130 5
}
131 5
/**
132 5
 * The {@link Instance} class represents a [Cloud Spanner
133 5
 * instance](https://cloud.google.com/spanner/docs/instances).
134 5
 *
135 5
 * Create an `Instance` object to interact with a Cloud Spanner instance.
136 5
 *
137 5
 * @class
138 5
 *
139 5
 * @param {Spanner} spanner {@link Spanner} instance.
140 5
 * @param {string} name Name of the instance.
141 5
 *
142 5
 * @example
143 5
 * const {Spanner} = require('@google-cloud/spanner');
144 5
 * const spanner = new Spanner();
145 5
 * const instance = spanner.instance('my-instance');
146 5
 */
147 5
class Instance extends common.GrpcServiceObject {
148 5
  formattedName_: string;
149 5
  request: InstanceRequest;
150 5
  requestStream: (config: RequestConfig) => Duplex;
151 5
  databases_: Map<string, Database>;
152 5
  metadata?: IInstance;
153 5
  resourceHeader_: {[k: string]: string};
154 5
  constructor(spanner: Spanner, name: string) {
155 5
    const formattedName_ = Instance.formatName_(spanner.projectId, name);
156 5
    const methods = {
157 5
      /**
158 5
       * Create an instance.
159 5
       *
160 5
       * Wrapper around {@link v1.InstanceAdminClient#createInstance}.
161 5
       *
162 5
       * @see {@link v1.InstanceAdminClient#createInstance}
163 5
       * @see [CreateInstance API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.instance.v1#google.spanner.admin.instance.v1.InstanceAdmin.CreateInstance)
164 5
       *
165 5
       * @method Instance#create
166 5
       * @param {CreateInstanceRequest} config Configuration object.
167 5
       * @param {CreateInstanceCallback} [callback] Callback function.
168 5
       * @returns {Promise<CreateInstanceResponse>}
169 5
       *
170 5
       * @example
171 5
       * const {Spanner} = require('@google-cloud/spanner');
172 5
       * const spanner = new Spanner();
173 5
       *
174 5
       * const instance = spanner.instance('my-instance');
175 5
       *
176 5
       * instance.create(function(err, instance, operation, apiResponse) {
177 5
       *   if (err) {
178 5
       *     // Error handling omitted.
179 5
       *   }
180 5
       *
181 5
       *   operation
182 5
       *     .on('error', function(err) {})
183 5
       *     .on('complete', function() {
184 5
       *       // Instance created successfully.
185 5
       *     });
186 5
       * });
187 5
       *
188 5
       * //-
189 5
       * // If the callback is omitted, we'll return a Promise.
190 5
       * //-
191 5
       * instance.create()
192 5
       *   .then(function(data) {
193 5
       *     const operation = data[0];
194 5
       *     const apiResponse = data[1];
195 5
       *
196 5
       *     return operation.promise();
197 5
       *   })
198 5
       *   .then(function() {
199 5
       *     // Instance created successfully.
200 5
       *   });
201 5
       */
202 5
      create: true,
203 5
    };
204 5
    super(({
205 5
      parent: spanner,
206 5
      /**
207 5
       * @name Instance#id
208 5
       * @type {string}
209 5
       */
210 5
      id: name,
211 5
      methods,
212 5
      createMethod(
213 5
        _: {},
214 5
        options: CreateInstanceRequest,
215 5
        callback: CreateInstanceCallback
216 5
      ): void {
217 5
        spanner.createInstance(formattedName_, options, callback);
218 5
      },
219 5
    } as {}) as ServiceObjectConfig);
220 5
    this.formattedName_ = formattedName_;
221 5
    this.request = spanner.request.bind(spanner);
222 5
    this.requestStream = spanner.requestStream.bind(spanner);
223 5
    this.databases_ = new Map<string, Database>();
224 5
    this.resourceHeader_ = {
225 5
      [CLOUD_RESOURCE_HEADER]: this.formattedName_,
226 5
    };
227 5
  }
228 5

229 5
  /**
230 5
   * Get a reference to a Backup object.
231 5
   *
232 5
   * @throws {Error} If any parameter is not provided.
233 5
   *
234 5
   * @param {string} backupId The name of the backup.
235 5
   * @return {Backup} A Backup object.
236 5
   *
237 5
   * @example
238 5
   * const {Spanner} = require('@google-cloud/spanner');
239 5
   * const spanner = new Spanner();
240 5
   * const instance = spanner.instance('my-instance');
241 5
   * const backup = instance.backup('my-backup');
242 5
   */
243 5
  backup(backupId: string): Backup {
244 5
    if (!backupId) {
245 5
      throw new Error('A backup ID is required to create a Backup.');
246 5
    }
247 5

248 5
    return new Backup(this, backupId);
249 5
  }
250 5

251 5
  getBackups(options?: GetBackupsOptions): Promise<GetBackupsResponse>;
252 5
  getBackups(callback: GetBackupsCallback): void;
253 5
  getBackups(options: GetBackupsOptions, callback: GetBackupsCallback): void;
254 5
  /**
255 5
   * Query object for listing backups.
256 5
   *
257 5
   * @typedef {object} GetBackupsOptions
258 5
   * @property {string} [filter] An expression for filtering the results of the
259 5
   *     request. Filter can be configured as outlined in
260 5
   *     {@link v1.DatabaseAdminClient#listBackups}.
261 5
   * @property {number} [pageSize] Maximum number of results per page.
262 5
   * @property {string} [pageToken] A previously-returned page token
263 5
   *     representing part of the larger set of results to view.
264 5
   * @property {object} [gaxOptions] Request configuration options, outlined
265 5
   *     here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
266 5
   */
267 5
  /**
268 5
   * @typedef {array} GetBackupsResponse
269 5
   * @property {Backup[]} 0 Array of {@link Backup} instances.
270 5
   * @property {object} 1 A query object to receive more results.
271 5
   * @property {object} 2 The full API response.
272 5
   */
273 5
  /**
274 5
   * @callback GetBackupsCallback
275 5
   * @param {?Error} err Request error, if any.
276 5
   * @param {Backup[]} 0 Array of {@link Backup} instances.
277 5
   * @param {object} nextQuery A query object to receive more results.
278 5
   * @param {object} apiResponse The full API response.
279 5
   */
280 5
  /**
281 5
   * List backups on the instance.
282 5
   *
283 5
   * Both completed and in-progress backups are listed if no filter is supplied.
284 5
   *
285 5
   * @see {@link #backup}
286 5
   *
287 5
   * @param {GetBackupsOptions} [options] The query object for listing backups.
288 5
   * @param {gax.CallOptions} [options.gaxOptions] The request configuration
289 5
   *     options, outlined here:
290 5
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
291 5
   * @returns {Promise<GetBackupsResponse>} When resolved, contains a paged list
292 5
   *     of backups.
293 5
   *
294 5
   * @example
295 5
   * const {Spanner} = require('@google-cloud/spanner');
296 5
   * const spanner = new Spanner();
297 5
   * const instance = spanner.instance('my-instance');
298 5
   * const [backups] = await instance.getBackups();
299 5
   *
300 5
   * //-
301 5
   * // To manually handle pagination, set autoPaginate:false in gaxOptions.
302 5
   * //-
303 5
   * let pageToken = undefined;
304 5
   * do {
305 5
   *   const [backups, , response] = await instance.getBackups({
306 5
   *     pageSize: 3,
307 5
   *     pageToken,
308 5
   *     gaxOptions: {autoPaginate: false},
309 5
   *   });
310 5
   *   backups.forEach(backup => {
311 5
   *     // Do something with backup
312 5
   *   });
313 5
   *   pageToken = response.nextPageToken;
314 5
   * } while (pageToken);
315 5
   */
316 5
  getBackups(
317 5
    optionsOrCallback?: GetBackupsOptions | GetBackupsCallback,
318 5
    cb?: GetBackupsCallback
319 5
  ): void | Promise<GetBackupsResponse> {
320 5
    const callback =
321 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
322 5
    const options =
323 5
      typeof optionsOrCallback === 'object'
324 5
        ? optionsOrCallback
325 5
        : ({} as GetBackupsOptions);
326 5
    const gaxOpts = extend(true, {}, options.gaxOptions);
327 5
    let reqOpts = extend({}, options, {
328 5
      parent: this.formattedName_,
329 5
    });
330 5
    delete reqOpts.gaxOptions;
331 5

332 5
    // Copy over pageSize and pageToken values from gaxOptions.
333 5
    // However values set on options take precedence.
334 5
    if (gaxOpts) {
335 5
      reqOpts = extend(
336 5
        {},
337 5
        {
338 5
          pageSize: gaxOpts.pageSize,
339 5
          pageToken: gaxOpts.pageToken,
340 5
        },
341 5
        reqOpts
342 5
      );
343 5
      delete gaxOpts.pageSize;
344 5
      delete gaxOpts.pageToken;
345 5
    }
346 5

347 5
    this.request<
348 5
      IBackup,
349 5
      databaseAdmin.spanner.admin.database.v1.IListBackupsResponse
350 5
    >(
351 5
      {
352 5
        client: 'DatabaseAdminClient',
353 5
        method: 'listBackups',
354 5
        reqOpts,
355 5
        gaxOpts,
356 5
        headers: this.resourceHeader_,
357 5
      },
358 5
      (err, backups, nextPageRequest, ...args) => {
359 5
        let backupInstances: Backup[] | null = null;
360 5
        if (backups) {
361 5
          backupInstances = backups.map(backup => {
362 5
            const backupInstance = this.backup(backup.name!);
363 5
            backupInstance.metadata = backup;
364 5
            return backupInstance;
365 5
          });
366 5
        }
367 5
        const nextQuery = nextPageRequest!
368 5
          ? extend({}, options, nextPageRequest!)
369 5
          : null;
370 5

371 5
        callback(err, backupInstances, nextQuery, ...args);
372 5
      }
373 5
    );
374 5
  }
375 5

376 5
  /**
377 5
   * Get a list of backups as a readable object stream.
378 5
   *
379 5
   * Wrapper around {@link v1.DatabaseAdminClient#listBackups}.
380 5
   *
381 5
   * @see {@link v1.DatabaseAdminClient#listBackups}
382 5
   * @see [ListBackups API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.database.v1#google.spanner.admin.database.v1.DatabaseAdmin.ListBackups)
383 5
   *
384 5
   * @method Spanner#getBackupsStream
385 5
   * @param {GetBackupOptions} [options] Query object for listing backups.
386 5
   * @returns {ReadableStream} A readable stream that emits {@link Backup}
387 5
   *     instances.
388 5
   *
389 5
   * @example
390 5
   * const {Spanner} = require('@google-cloud/spanner');
391 5
   * const spanner = new Spanner();
392 5
   *
393 5
   * const instance = spanner.instance('my-instance');
394 5
   *
395 5
   * instance.getBackupsStream()
396 5
   *   .on('error', console.error)
397 5
   *   .on('data', function(database) {
398 5
   *     // `backups` is a `Backup` object.
399 5
   *   })
400 5
   *   .on('end', function() {
401 5
   *     // All backups retrieved.
402 5
   *   });
403 5
   *
404 5
   * //-
405 5
   * // If you anticipate many results, you can end a stream early to prevent
406 5
   * // unnecessary processing and API requests.
407 5
   * //-
408 5
   * instance.getBackupsStream()
409 5
   *   .on('data', function(database) {
410 5
   *     this.end();
411 5
   *   });
412 5
   */
413 5
  getBackupsStream(options: GetBackupsOptions = {}): NodeJS.ReadableStream {
414 5
    const gaxOpts = extend(true, {}, options.gaxOptions);
415 5

416 5
    let reqOpts = extend({}, options, {
417 5
      parent: this.formattedName_,
418 5
    });
419 5
    delete reqOpts.gaxOptions;
420 5

421 5
    // Copy over pageSize and pageToken values from gaxOptions.
422 5
    // However values set on options take precedence.
423 5
    if (gaxOpts) {
424 5
      reqOpts = extend(
425 5
        {},
426 5
        {
427 5
          pageSize: gaxOpts.pageSize,
428 5
          pageToken: gaxOpts.pageToken,
429 5
        },
430 5
        reqOpts
431 5
      );
432 5
      delete gaxOpts.pageSize;
433 5
      delete gaxOpts.pageToken;
434 5
    }
435 5

436 5
    return this.requestStream({
437 5
      client: 'DatabaseAdminClient',
438 5
      method: 'listBackupsStream',
439 5
      reqOpts,
440 5
      gaxOpts,
441 5
      headers: this.resourceHeader_,
442 5
    });
443 5
  }
444 5

445 5
  getBackupOperations(
446 5
    options?: GetBackupOperationsOptions
447 5
  ): Promise<GetBackupOperationsResponse>;
448 5
  getBackupOperations(callback: GetBackupOperationsCallback): void;
449 5
  getBackupOperations(
450 5
    options: GetBackupOperationsOptions,
451 5
    callback: GetBackupOperationsCallback
452 5
  ): void;
453 5
  /**
454 5
   * Query object for listing backup operations.
455 5
   *
456 5
   * @typedef {object} GetBackupOperationsOptions
457 5
   * @property {string} [filter] An expression for filtering the results of the
458 5
   *     request. Filter can be configured as outlined in
459 5
   *     {@link v1.DatabaseAdminClient#listBackupOperations}.
460 5
   * @property {number} [pageSize] Maximum number of results per page.
461 5
   * @property {string} [pageToken] A previously-returned page token
462 5
   *     representing part of the larger set of results to view.
463 5
   * @property {object} [gaxOptions] Request configuration options, outlined
464 5
   *     here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
465 5
   */
466 5
  /**
467 5
   * @typedef {array} GetBackupOperationsResponse
468 5
   * @property {IOperation[]} 0 Array of {@link IOperation} instances.
469 5
   * @property {object} 1 A query object to receive more results.
470 5
   * @property {object} 2 The full API response.
471 5
   */
472 5
  /**
473 5
   * @callback GetBackupOperationsCallback
474 5
   * @param {?Error} err Request error, if any.
475 5
   * @param {IOperation[]} 0 Array of {@link IOperation} instances.
476 5
   * @param {object} nextQuery A query object to receive more results.
477 5
   * @param {object} apiResponse The full API response.
478 5
   */
479 5

480 5
  /**
481 5
   * List pending and completed backup operations for all databases in the instance.
482 5
   *
483 5
   * @see {@link #listOperations}
484 5
   *
485 5
   * @param {GetBackupOperationsOptions} [options] The query object for listing
486 5
   *     backup operations.
487 5
   * @param {gax.CallOptions} [options.gaxOptions] The request configuration
488 5
   *     options, outlined here:
489 5
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
490 5
   * @returns {Promise<GetBackupOperationsResponse>} When resolved, contains a
491 5
   *     paged list of backup operations.
492 5
   *
493 5
   * @example
494 5
   * const {Spanner} = require('@google-cloud/spanner');
495 5
   * const spanner = new Spanner();
496 5
   * const instance = spanner.instance('my-instance');
497 5
   * const [operations] = await instance.getBackupOperations();
498 5
   *
499 5
   * //-
500 5
   * // To manually handle pagination, set autoPaginate:false in gaxOptions.
501 5
   * //-
502 5
   * let pageToken = undefined;
503 5
   * do {
504 5
   *   const [operations, , response] = await instance.getBackupOperations({
505 5
   *     pageSize: 3,
506 5
   *     pageToken,
507 5
   *     gaxOptions: {autoPaginate: false},
508 5
   *   });
509 5
   *   operations.forEach(operation => {
510 5
   *     // Do something with operation
511 5
   *   });
512 5
   *   pageToken = response.nextPageToken;
513 5
   * } while (pageToken);
514 5
   */
515 5
  getBackupOperations(
516 5
    optionsOrCallback?:
517 5
      | GetBackupOperationsOptions
518 5
      | GetBackupOperationsCallback,
519 5
    cb?: GetBackupOperationsCallback
520 5
  ): void | Promise<GetBackupOperationsResponse> {
521 5
    const callback =
522 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
523 5
    const options =
524 5
      typeof optionsOrCallback === 'object'
525 5
        ? optionsOrCallback
526 5
        : ({} as GetBackupOperationsOptions);
527 5
    const gaxOpts = extend(true, {}, options.gaxOptions);
528 5
    let reqOpts = extend({}, options, {
529 5
      parent: this.formattedName_,
530 5
    });
531 5
    delete reqOpts.gaxOptions;
532 5

533 5
    // Copy over pageSize and pageToken values from gaxOptions.
534 5
    // However values set on options take precedence.
535 5
    if (gaxOpts) {
536 5
      reqOpts = extend(
537 5
        {},
538 5
        {
539 5
          pageSize: gaxOpts.pageSize,
540 5
          pageToken: gaxOpts.pageToken,
541 5
        },
542 5
        reqOpts
543 5
      );
544 5
      delete gaxOpts.pageSize;
545 5
      delete gaxOpts.pageToken;
546 5
    }
547 5

548 5
    this.request<
549 5
      IOperation,
550 5
      databaseAdmin.spanner.admin.database.v1.IListBackupOperationsResponse
551 5
    >(
552 5
      {
553 5
        client: 'DatabaseAdminClient',
554 5
        method: 'listBackupOperations',
555 5
        reqOpts,
556 5
        gaxOpts,
557 5
        headers: this.resourceHeader_,
558 5
      },
559 5
      (err, operations, nextPageRequest, ...args) => {
560 5
        const nextQuery = nextPageRequest!
561 5
          ? extend({}, options, nextPageRequest!)
562 5
          : null;
563 5

564 5
        callback!(err, operations, nextQuery, ...args);
565 5
      }
566 5
    );
567 5
  }
568 5

569 5
  getDatabaseOperations(
570 5
    options?: GetDatabaseOperationsOptions
571 5
  ): Promise<GetDatabaseOperationsResponse>;
572 5
  getDatabaseOperations(callback: GetDatabaseOperationsCallback): void;
573 5
  getDatabaseOperations(
574 5
    options: GetDatabaseOperationsOptions,
575 5
    callback: GetDatabaseOperationsCallback
576 5
  ): void;
577 5
  /**
578 5
   * Query object for listing database operations.
579 5
   *
580 5
   * @typedef {object} GetDatabaseOperationsOptions
581 5
   * @property {string} [filter] An expression for filtering the results of the
582 5
   *     request. Filter can be configured as outlined in
583 5
   *     {@link v1.DatabaseAdminClient#listDatabaseOperations}.
584 5
   * @property {number} [pageSize] Maximum number of results per page.
585 5
   * @property {string} [pageToken] A previously-returned page token
586 5
   *     representing part of the larger set of results to view.
587 5
   * @property {object} [gaxOptions] Request configuration options, outlined
588 5
   *     here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
589 5
   */
590 5
  /**
591 5
   * @typedef {array} GetDatabaseOperationsResponse
592 5
   * @property {IOperation[]} 0 Array of {@link IOperation} instances.
593 5
   * @property {object} 1 A query object to receive more results.
594 5
   * @property {object} 2 The full API response.
595 5
   */
596 5
  /**
597 5
   * @callback GetDatabaseOperationsCallback
598 5
   * @param {?Error} err Request error, if any.
599 5
   * @param {IOperation[]} 0 Array of {@link IOperation} instances.
600 5
   * @param {object} nextQuery A query object to receive more results.
601 5
   * @param {object} apiResponse The full API response.
602 5
   */
603 5

604 5
  /**
605 5
   * List pending and completed operations for all databases in the instance.
606 5
   *
607 5
   * @see {@link Database.getDatabaseOperations}
608 5
   *
609 5
   * @param {GetDatabaseOperationsOptions} [options] The query object for
610 5
   *     listing database operations.
611 5
   * @param {gax.CallOptions} [options.gaxOptions] The request configuration
612 5
   *     options, outlined here:
613 5
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
614 5
   * @returns {Promise<GetDatabaseOperationsResponse>} When resolved, contains a
615 5
   *     paged list of database operations.
616 5
   *
617 5
   * @example
618 5
   * const {Spanner} = require('@google-cloud/spanner');
619 5
   * const spanner = new Spanner();
620 5
   * const instance = spanner.instance('my-instance');
621 5
   * const [operations] = await instance.getDatabaseOperations();
622 5
   * // ... then do something with the operations
623 5
   *
624 5
   * //-
625 5
   * // To manually handle pagination, set autoPaginate:false in gaxOptions.
626 5
   * //-
627 5
   * let pageToken = undefined;
628 5
   * do {
629 5
   *   const [operations, , response] = await instance.getDatabaseOperations({
630 5
   *     pageSize: 3,
631 5
   *     pageToken,
632 5
   *     gaxOptions: {autoPaginate: false},
633 5
   *   });
634 5
   *   operations.forEach(operation => {
635 5
   *     // Do something with operation
636 5
   *   });
637 5
   *   pageToken = response.nextPageToken;
638 5
   * } while (pageToken);
639 5
   */
640 5
  getDatabaseOperations(
641 5
    optionsOrCallback?:
642 5
      | GetDatabaseOperationsOptions
643 5
      | GetDatabaseOperationsCallback,
644 5
    cb?: GetDatabaseOperationsCallback
645 5
  ): void | Promise<GetDatabaseOperationsResponse> {
646 5
    const callback =
647 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
648 5
    const options =
649 5
      typeof optionsOrCallback === 'object'
650 5
        ? optionsOrCallback
651 5
        : ({} as GetDatabaseOperationsOptions);
652 5
    const gaxOpts = extend(true, {}, options.gaxOptions);
653 5
    let reqOpts = extend({}, options, {
654 5
      parent: this.formattedName_,
655 5
    });
656 5
    delete reqOpts.gaxOptions;
657 5

658 5
    // Copy over pageSize and pageToken values from gaxOptions.
659 5
    // However values set on options take precedence.
660 5
    if (gaxOpts) {
661 5
      reqOpts = extend(
662 5
        {},
663 5
        {
664 5
          pageSize: gaxOpts.pageSize,
665 5
          pageToken: gaxOpts.pageToken,
666 5
        },
667 5
        reqOpts
668 5
      );
669 5
      delete gaxOpts.pageSize;
670 5
      delete gaxOpts.pageToken;
671 5
    }
672 5

673 5
    this.request<
674 5
      IOperation,
675 5
      databaseAdmin.spanner.admin.database.v1.IListDatabaseOperationsResponse
676 5
    >(
677 5
      {
678 5
        client: 'DatabaseAdminClient',
679 5
        method: 'listDatabaseOperations',
680 5
        reqOpts,
681 5
        gaxOpts,
682 5
        headers: this.resourceHeader_,
683 5
      },
684 5
      (err, operations, nextPageRequest, ...args) => {
685 5
        const nextQuery = nextPageRequest!
686 5
          ? extend({}, options, nextPageRequest!)
687 5
          : null;
688 5

689 5
        callback!(err, operations, nextQuery, ...args);
690 5
      }
691 5
    );
692 5
  }
693 5

694 5
  createDatabase(
695 5
    name: string,
696 5
    options?: CreateDatabaseOptions
697 5
  ): Promise<CreateDatabaseResponse>;
698 5
  createDatabase(name: string, callback: CreateDatabaseCallback): void;
699 5
  createDatabase(
700 5
    name: string,
701 5
    options: CreateDatabaseOptions,
702 5
    callback: CreateDatabaseCallback
703 5
  ): void;
704 5
  /**
705 5
   * Config for the new database.
706 5
   *
707 5
   * @typedef {object} CreateDatabaseRequest
708 5
   * @property {SessionPoolOptions} [poolOptions]
709 5
   * @property {SessionPoolCtor} [poolCtor]
710 5
   */
711 5
  /**
712 5
   * @typedef {array} CreateDatabaseResponse
713 5
   * @property {Database} 0 The new {@link Database}.
714 5
   * @property {Operation} 1 An {@link Operation} object that can be used to check
715 5
   *     the status of the request.
716 5
   * @property {object} 2 The full API response.
717 5
   */
718 5
  /**
719 5
   * @callback CreateDatabaseCallback
720 5
   * @param {?Error} err Request error, if any.
721 5
   * @param {Database} database The new {@link Database}.
722 5
   * @param {Operation} operation An {@link Operation} object that can be used to
723 5
   *     check the status of the request.
724 5
   * @param {object} apiResponse The full API response.
725 5
   */
726 5
  /**
727 5
   * Create a database in this instance.
728 5
   *
729 5
   * Wrapper around {@link v1.DatabaseAdminClient#createDatabase}.
730 5
   *
731 5
   * @see {@link v1.DatabaseAdminClient#createDatabase}
732 5
   * @see [CreateDatabase API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.database.v1#google.spanner.admin.database.v1.DatabaseAdmin.CreateDatabase)
733 5
   *
734 5
   * @throws {Error} If a name is not provided.
735 5
   *
736 5
   * @param {name} name The name of the database to create.
737 5
   * @param {CreateDatabaseRequest} [options] Configuration object.
738 5
   * @param {CreateDatabaseCallback} [callback] Callback function.
739 5
   * @returns {Promise<CreateDatabaseResponse>}
740 5
   *
741 5
   * @example
742 5
   * const {Spanner} = require('@google-cloud/spanner');
743 5
   * const spanner = new Spanner();
744 5
   *
745 5
   * const instance = spanner.instance('my-instance');
746 5
   *
747 5
   * function callback(err, database, operation, apiResponse) {
748 5
   *   if (err) {
749 5
   *     // Error handling omitted.
750 5
   *   }
751 5
   *
752 5
   *   operation
753 5
   *     .on('error', function(err) {})
754 5
   *     .on('complete', function() {
755 5
   *       // Database created successfully.
756 5
   *     });
757 5
   * }
758 5
   *
759 5
   * instance.createDatabase('new-database-name', callback);
760 5
   *
761 5
   * //-
762 5
   * // Set the schema for the database.
763 5
   * //-
764 5
   * instance.createDatabase('new-database-name', {
765 5
   *   schema:
766 5
   *     'CREATE TABLE Singers (' +
767 5
   *     '  SingerId STRING(1024) NOT NULL,' +
768 5
   *     '  Name STRING(1024),' +
769 5
   *     ') PRIMARY KEY(SingerId)'
770 5
   * }, callback);
771 5
   * //-
772 5
   * // If the callback is omitted, we'll return a Promise.
773 5
   * //-
774 5
   * instance.createDatabase('new-database-name')
775 5
   *   .then(function(data) {
776 5
   *     const database = data[0];
777 5
   *     const operation = data[1];
778 5
   *     return operation.promise();
779 5
   *   })
780 5
   *   .then(function() {
781 5
   *     // Database created successfully.
782 5
   *   });
783 5
   *
784 5
   * @example <caption>include:samples/schema.js</caption>
785 5
   * region_tag:spanner_create_database
786 5
   * Full example:
787 5
   */
788 5
  createDatabase(
789 5
    name: string,
790 5
    optionsOrCallback?: CreateDatabaseOptions | CreateDatabaseCallback,
791 5
    cb?: CreateDatabaseCallback
792 5
  ): void | Promise<CreateDatabaseResponse> {
793 5
    if (!name) {
794 5
      throw new Error('A name is required to create a database.');
795 5
    }
796 5
    const callback =
797 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
798 5
    const options =
799 5
      typeof optionsOrCallback === 'object'
800 5
        ? optionsOrCallback
801 5
        : ({} as CreateDatabaseOptions);
802 5

803 5
    const poolOptions = options.poolOptions;
804 5
    const poolCtor = options.poolCtor;
805 5
    const reqOpts = extend(
806 5
      {
807 5
        parent: this.formattedName_,
808 5
        createStatement: 'CREATE DATABASE `' + name.split('/').pop() + '`',
809 5
      },
810 5
      options
811 5
    );
812 5

813 5
    delete reqOpts.poolOptions;
814 5
    delete reqOpts.poolCtor;
815 5
    delete reqOpts.gaxOptions;
816 5

817 5
    if (reqOpts.schema) {
818 5
      reqOpts.extraStatements = arrify(reqOpts.schema);
819 5
      delete reqOpts.schema;
820 5
    }
821 5
    this.request(
822 5
      {
823 5
        client: 'DatabaseAdminClient',
824 5
        method: 'createDatabase',
825 5
        reqOpts,
826 5
        gaxOpts: options.gaxOptions,
827 5
        headers: this.resourceHeader_,
828 5
      },
829 5
      (err, operation, resp) => {
830 5
        if (err) {
831 5
          callback(err, null, null, resp);
832 5
          return;
833 5
        }
834 5
        const database = this.database(name, poolOptions || poolCtor);
835 5
        callback(null, database, operation, resp);
836 5
      }
837 5
    );
838 5
  }
839 5

840 5
  /**
841 5
   * Get a reference to a Database object.
842 5
   *
843 5
   * @throws {Error} If a name is not provided.
844 5
   *
845 5
   * @param {string} name The name of the instance.
846 5
   * @param {SessionPoolOptions|SessionPoolCtor} [poolOptions] Session pool
847 5
   *     configuration options.
848 5
   * @param {spannerClient.spanner.v1.ExecuteSqlRequest.IQueryOptions} [queryOptions]
849 5
   *     Default query options to use with the database. These options will be
850 5
   *     overridden by any query options set in environment variables or that
851 5
   *     are specified on a per-query basis.
852 5
   * @return {Database} A Database object.
853 5
   *
854 5
   * @example
855 5
   * const {Spanner} = require('@google-cloud/spanner');
856 5
   * const spanner = new Spanner();
857 5
   *
858 5
   * const instance = spanner.instance('my-instance');
859 5
   * const database = instance.database('my-database');
860 5
   */
861 5
  database(
862 5
    name: string,
863 5
    poolOptions?: SessionPoolOptions | SessionPoolConstructor,
864 5
    queryOptions?: spannerClient.spanner.v1.ExecuteSqlRequest.IQueryOptions
865 5
  ): Database {
866 5
    if (!name) {
867 5
      throw new Error('A name is required to access a Database object.');
868 5
    }
869 5
    // Only add an additional key for SessionPoolOptions and QueryOptions if an
870 5
    // options object with at least one value was passed in.
871 5
    let optionsKey =
872 5
      poolOptions && Object.keys(poolOptions).length > 0
873 5
        ? '/' + JSON.stringify(Object.entries(poolOptions).sort())
874 5
        : '';
875 5
    if (queryOptions && Object.keys(queryOptions).length > 0) {
876 5
      optionsKey =
877 5
        optionsKey + '/' + JSON.stringify(Object.entries(queryOptions!).sort());
878 5
    }
879 5
    const key = name.split('/').pop() + optionsKey;
880 5
    if (!this.databases_.has(key!)) {
881 5
      this.databases_.set(
882 5
        key!,
883 5
        new Database(this, name, poolOptions, queryOptions)
884 5
      );
885 5
    }
886 5
    return this.databases_.get(key!)!;
887 5
  }
888 5

889 5
  delete(gaxOptions?: CallOptions): Promise<DeleteInstanceResponse>;
890 5
  delete(callback: DeleteInstanceCallback): void;
891 5
  delete(gaxOptions: CallOptions, callback: DeleteInstanceCallback): void;
892 5
  /**
893 5
   * @typedef {array} DeleteInstanceResponse
894 5
   * @property {object} 0 The full API response.
895 5
   */
896 5
  /**
897 5
   * @callback DeleteInstanceCallback
898 5
   * @param {?Error} err Request error, if any.
899 5
   * @param {object} apiResponse The full API response.
900 5
   */
901 5
  /**
902 5
   * Delete the instance.
903 5
   *
904 5
   * Wrapper around {@link v1.InstanceAdminClient#deleteInstance}.
905 5
   *
906 5
   * @see {@link v1.InstanceAdminClient#deleteInstance}
907 5
   * @see [DeleteInstance API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.instance.v1#google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstance)
908 5
   *
909 5
   * @param {object} [gaxOptions] Request configuration options, outlined here:
910 5
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
911 5
   * @param {DeleteInstanceCallback} [callback] Callback function.
912 5
   * @returns {Promise<DeleteInstanceResponse>}
913 5
   *
914 5
   * @example
915 5
   * const {Spanner} = require('@google-cloud/spanner');
916 5
   * const spanner = new Spanner();
917 5
   *
918 5
   * const instance = spanner.instance('my-instance');
919 5
   *
920 5
   * instance.delete(function(err, apiResponse) {
921 5
   *   if (err) {
922 5
   *     // Error handling omitted.
923 5
   *   }
924 5
   *
925 5
   *   // Instance was deleted successfully.
926 5
   * });
927 5
   *
928 5
   * //-
929 5
   * // If the callback is omitted, we'll return a Promise.
930 5
   * //-
931 5
   * instance.delete().then(function(data) {
932 5
   *   const apiResponse = data[0];
933 5
   * });
934 5
   */
935 5
  delete(
936 5
    optionsOrCallback?: CallOptions | DeleteInstanceCallback,
937 5
    cb?: DeleteInstanceCallback
938 5
  ): void | Promise<DeleteInstanceResponse> {
939 5
    const gaxOpts =
940 5
      typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
941 5
    const callback =
942 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
943 5

944 5
    const reqOpts = {
945 5
      name: this.formattedName_,
946 5
    };
947 5
    Promise.all(
948 5
      Array.from(this.databases_.values()).map(database => {
949 5
        return database.close();
950 5
      })
951 5
    )
952 5
      .catch(() => {})
953 5
      .then(() => {
954 5
        this.databases_.clear();
955 5
        this.request<instanceAdmin.protobuf.IEmpty>(
956 5
          {
957 5
            client: 'InstanceAdminClient',
958 5
            method: 'deleteInstance',
959 5
            reqOpts,
960 5
            gaxOpts,
961 5
            headers: this.resourceHeader_,
962 5
          },
963 5
          (err, resp) => {
964 5
            if (!err) {
965 5
              this.parent.instances_.delete(this.id);
966 5
            }
967 5
            callback!(err, resp!);
968 5
          }
969 5
        );
970 5
      });
971 5
  }
972 5

973 5
  exists(gaxOptions?: CallOptions): Promise<ExistsInstanceResponse>;
974 5
  exists(callback: ExistsInstanceCallback): void;
975 5
  exists(gaxOptions: CallOptions, callback: ExistsInstanceCallback): void;
976 5
  /**
977 5
   * @typedef {array} InstanceExistsResponse
978 5
   * @property {boolean} 0 Whether the {@link Instance} exists.
979 5
   */
980 5
  /**
981 5
   * @callback InstanceExistsCallback
982 5
   * @param {?Error} err Request error, if any.
983 5
   * @param {boolean} exists Whether the {@link Instance} exists.
984 5
   */
985 5
  /**
986 5
   * Check if an instance exists.
987 5
   *
988 5
   * @method Instance#exists
989 5
   * @param {object} [gaxOptions] Request configuration options, outlined here:
990 5
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
991 5
   * @param {InstanceExistsCallback} [callback] Callback function.
992 5
   * @returns {Promise<InstanceExistsResponse>}
993 5
   *
994 5
   * @example
995 5
   * const {Spanner} = require('@google-cloud/spanner');
996 5
   * const spanner = new Spanner();
997 5
   *
998 5
   * const instance = spanner.instance('my-instance');
999 5
   *
1000 5
   * instance.exists(function(err, exists) {});
1001 5
   *
1002 5
   * //-
1003 5
   * // If the callback is omitted, we'll return a Promise.
1004 5
   * //-
1005 5
   * instance.exists().then(function(data) {
1006 5
   *   const exists = data[0];
1007 5
   * });
1008 5
   */
1009 5
  exists(
1010 5
    optionsOrCallback?: CallOptions | ExistsInstanceCallback,
1011 5
    cb?: ExistsInstanceCallback
1012 5
  ): void | Promise<ExistsInstanceResponse> {
1013 5
    const gaxOptions =
1014 5
      typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
1015 5
    const callback =
1016 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
1017 5

1018 5
    const NOT_FOUND = 5;
1019 5

1020 5
    this.getMetadata({gaxOptions}, err => {
1021 5
      if (err && err.code !== NOT_FOUND) {
1022 5
        callback!(err, null);
1023 5
        return;
1024 5
      }
1025 5

1026 5
      const exists = !err || err.code !== NOT_FOUND;
1027 5
      callback!(null, exists);
1028 5
    });
1029 5
  }
1030 5

1031 5
  get(options?: GetInstanceConfig): Promise<GetInstanceResponse>;
1032 5
  get(callback: GetInstanceCallback): void;
1033 5
  get(options: GetInstanceConfig, callback: GetInstanceCallback): void;
1034 5
  /**
1035 5
   * @typedef {array} GetInstanceResponse
1036 5
   * @property {Instance} 0 The {@link Instance}.
1037 5
   * @property {object} 1 The full API response.
1038 5
   */
1039 5
  /**
1040 5
   * @callback GetInstanceCallback
1041 5
   * @param {?Error} err Request error, if any.
1042 5
   * @param {Instance} instance The {@link Instance}.
1043 5
   * @param {object} apiResponse The full API response.
1044 5
   */
1045 5
  /**
1046 5
   * Get an instance if it exists.
1047 5
   *
1048 5
   * You may optionally use this to "get or create" an object by providing an
1049 5
   * object with `autoCreate` set to `true`. Any extra configuration that is
1050 5
   * normally required for the `create` method must be contained within this
1051 5
   * object as well.
1052 5
   *
1053 5
   * @param {options} [options] Configuration object.
1054 5
   * @param {boolean} [options.autoCreate=false] Automatically create the
1055 5
   *     object if it does not exist.
1056 5
   * @param {string | string[]} [options.fieldNames] A list of `Instance` field
1057 5
   *     names to be requested. Eligible values are: `name`, `displayName`,
1058 5
   *     `endpointUris`, `labels`, `config`, `nodeCount`, `state`.
1059 5
   * @param {GetInstanceCallback} [callback] Callback function.
1060 5
   * @returns {Promise<GetInstanceResponse>}
1061 5
   *
1062 5
   * @example
1063 5
   * const {Spanner} = require('@google-cloud/spanner');
1064 5
   * const spanner = new Spanner();
1065 5
   *
1066 5
   * const instance = spanner.instance('my-instance');
1067 5
   *
1068 5
   * instance.get(function(err, instance, apiResponse) {
1069 5
   *   // `instance.metadata` has been populated.
1070 5
   * });
1071 5
   *
1072 5
   * //-
1073 5
   * // If the callback is omitted, we'll return a Promise.
1074 5
   * //-
1075 5
   * instance.get().then(function(data) {
1076 5
   *   const instance = data[0];
1077 5
   *   const apiResponse = data[0];
1078 5
   * });
1079 5
   */
1080 5
  get(
1081 5
    optionsOrCallback?: GetInstanceConfig | GetInstanceCallback,
1082 5
    cb?: GetInstanceCallback
1083 5
  ): void | Promise<GetInstanceResponse> {
1084 5
    const callback =
1085 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
1086 5
    const options =
1087 5
      typeof optionsOrCallback === 'object'
1088 5
        ? optionsOrCallback
1089 5
        : ({} as GetInstanceConfig);
1090 5

1091 5
    const getMetadataOptions: GetInstanceMetadataOptions = new Object(null);
1092 5
    if (options.fieldNames) {
1093 5
      getMetadataOptions.fieldNames = options.fieldNames;
1094 5
    }
1095 5
    if (options.gaxOptions) {
1096 5
      getMetadataOptions.gaxOptions = options.gaxOptions;
1097 5
    }
1098 5

1099 5
    this.getMetadata(getMetadataOptions, (err, metadata) => {
1100 5
      if (err) {
1101 5
        if (err.code === 5 && options.autoCreate) {
1102 5
          const createOptions = extend(true, {}, options);
1103 5
          delete createOptions.fieldNames;
1104 5
          delete createOptions.autoCreate;
1105 5
          this.create(
1106 5
            createOptions,
1107 5
            (
1108 5
              err: grpc.ServiceError | null,
1109 5
              instance?: Instance,
1110 5
              operation?: GaxOperation | null
1111 5
            ) => {
1112 5
              if (err) {
1113 5
                callback(err);
1114 5
                return;
1115 5
              }
1116 5
              operation!
1117 5
                .on('error', callback)
1118 5
                .on('complete', (metadata: IInstance) => {
1119 5
                  this.metadata = metadata;
1120 5
                  callback(null, this, metadata);
1121 5
                });
1122 5
            }
1123 5
          );
1124 5
          return;
1125 5
        }
1126 5
        callback(err);
1127 5
        return;
1128 5
      }
1129 5
      callback(null, this, metadata!);
1130 5
    });
1131 5
  }
1132 5

1133 5
  getDatabases(options?: GetDatabasesOptions): Promise<GetDatabasesResponse>;
1134 5
  getDatabases(callback: GetDatabasesCallback): void;
1135 5
  getDatabases(
1136 5
    options: GetDatabasesOptions,
1137 5
    callback: GetDatabasesCallback
1138 5
  ): void;
1139 5
  /**
1140 5
   * Query object for listing databases.
1141 5
   *
1142 5
   * @typedef {object} GetDatabasesRequest
1143 5
   * @property {number} [pageSize] Maximum number of results per page.
1144 5
   * @property {string} [pageToken] A previously-returned page token
1145 5
   *     representing part of the larger set of results to view.
1146 5
   * @property {object} [gaxOptions] Request configuration options, outlined
1147 5
   *     here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
1148 5
   */
1149 5
  /**
1150 5
   * @typedef {array} GetDatabasesResponse
1151 5
   * @property {Database[]} 0 Array of {@link Database} instances.
1152 5
   * @property {object} nextQuery A query object to receive more results.
1153 5
   * @property {object} apiResponse The full API response.
1154 5
   */
1155 5
  /**
1156 5
   * @callback GetDatabasesCallback
1157 5
   * @param {?Error} err Request error, if any.
1158 5
   * @param {Database[]} databases Array of {@link Database} instances.
1159 5
   * @param {object} nextQuery A query object to receive more results.
1160 5
   * @param {object} apiResponse The full API response.
1161 5
   */
1162 5
  /**
1163 5
   * Get a list of databases.
1164 5
   *
1165 5
   * Wrapper around {@link v1.DatabaseAdminClient#listDatabases}.
1166 5
   *
1167 5
   * @see {@link v1.DatabaseAdminClient#listDatabases}
1168 5
   * @see [ListDatabases API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.database.v1#google.spanner.admin.database.v1.DatabaseAdmin.ListDatabases)
1169 5
   *
1170 5
   * @param {GetDatabasesOptions} [options] Query object for listing databases.
1171 5
   * @param {GetDatabasesCallback} [callback] Callback function.
1172 5
   * @returns {Promise<GetDatabasesResponse>}
1173 5
   *
1174 5
   * @example
1175 5
   * const {Spanner} = require('@google-cloud/spanner');
1176 5
   * const spanner = new Spanner();
1177 5
   *
1178 5
   * const instance = spanner.instance('my-instance');
1179 5
   *
1180 5
   * instance.getDatabases(function(err, databases) {
1181 5
   *   // `databases` is an array of `Database` objects.
1182 5
   * });
1183 5
   *
1184 5
   * //-
1185 5
   * // To control how many API requests are made and page through the results
1186 5
   * // manually, set `autoPaginate` to `false`.
1187 5
   * //-
1188 5
   * function callback(err, databases, nextQuery, apiResponse) {
1189 5
   *   if (nextQuery) {
1190 5
   *     // More results exist.
1191 5
   *     instance.getDatabases(nextQuery, callback);
1192 5
   *   }
1193 5
   * }
1194 5
   *
1195 5
   * instance.getDatabases({
1196 5
   *   gaxOptions: {autoPaginate: false}
1197 5
   * }, callback);
1198 5
   *
1199 5
   * //-
1200 5
   * // If the callback is omitted, we'll return a Promise.
1201 5
   * //-
1202 5
   * instance.getDatabases().then(function(data) {
1203 5
   *   const databases = data[0];
1204 5
   * });
1205 5
   */
1206 5
  getDatabases(
1207 5
    optionsOrCallback?: GetDatabasesOptions | GetDatabasesCallback,
1208 5
    cb?: GetDatabasesCallback
1209 5
  ): void | Promise<GetDatabasesResponse> {
1210 5
    // eslint-disable-next-line @typescript-eslint/no-this-alias
1211 5
    const self = this;
1212 5
    const callback =
1213 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
1214 5
    const options =
1215 5
      typeof optionsOrCallback === 'object'
1216 5
        ? optionsOrCallback
1217 5
        : ({} as GetDatabasesOptions);
1218 5

1219 5
    const gaxOpts = extend(true, {}, options.gaxOptions);
1220 5
    let reqOpts = extend({}, options, {
1221 5
      parent: this.formattedName_,
1222 5
    });
1223 5
    delete reqOpts.gaxOptions;
1224 5

1225 5
    // Copy over pageSize and pageToken values from gaxOptions.
1226 5
    // However values set on options take precedence.
1227 5
    if (gaxOpts) {
1228 5
      reqOpts = extend(
1229 5
        {},
1230 5
        {
1231 5
          pageSize: gaxOpts.pageSize,
1232 5
          pageToken: gaxOpts.pageToken,
1233 5
        },
1234 5
        reqOpts
1235 5
      );
1236 5
      delete gaxOpts.pageSize;
1237 5
      delete gaxOpts.pageToken;
1238 5
    }
1239 5

1240 5
    this.request<
1241 5
      IDatabase,
1242 5
      databaseAdmin.spanner.admin.database.v1.IListDatabasesResponse
1243 5
    >(
1244 5
      {
1245 5
        client: 'DatabaseAdminClient',
1246 5
        method: 'listDatabases',
1247 5
        reqOpts,
1248 5
        gaxOpts,
1249 5
        headers: this.resourceHeader_,
1250 5
      },
1251 5
      (err, rowDatabases, nextPageRequest, ...args) => {
1252 5
        let databases: Database[] | null = null;
1253 5
        if (rowDatabases) {
1254 5
          databases = rowDatabases.map(database => {
1255 5
            const databaseInstance = self.database(database.name!, {min: 0});
1256 5
            databaseInstance.metadata = database;
1257 5
            return databaseInstance;
1258 5
          });
1259 5
        }
1260 5
        const nextQuery = nextPageRequest!
1261 5
          ? extend({}, options, nextPageRequest!)
1262 5
          : null;
1263 5

1264 5
        callback(err, databases, nextQuery, ...args);
1265 5
      }
1266 5
    );
1267 5
  }
1268 5

1269 5
  /**
1270 5
   * Get a list of databases as a readable object stream.
1271 5
   *
1272 5
   * Wrapper around {@link v1.DatabaseAdminClient#listDatabases}.
1273 5
   *
1274 5
   * @see {@link v1.DatabaseAdminClient#listDatabases}
1275 5
   * @see [ListDatabases API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.database.v1#google.spanner.admin.database.v1.DatabaseAdmin.ListDatabases)
1276 5
   *
1277 5
   * @method Spanner#getDatabasesStream
1278 5
   * @param {GetDatabasesOptions} [options] Query object for listing databases.
1279 5
   * @returns {ReadableStream} A readable stream that emits {@link Database}
1280 5
   *     instances.
1281 5
   *
1282 5
   * @example
1283 5
   * const {Spanner} = require('@google-cloud/spanner');
1284 5
   * const spanner = new Spanner();
1285 5
   *
1286 5
   * const instance = spanner.instance('my-instance');
1287 5
   *
1288 5
   * instance.getDatabasesStream()
1289 5
   *   .on('error', console.error)
1290 5
   *   .on('data', function(database) {
1291 5
   *     // `database` is a `Database` object.
1292 5
   *   })
1293 5
   *   .on('end', function() {
1294 5
   *     // All databases retrieved.
1295 5
   *   });
1296 5
   *
1297 5
   * //-
1298 5
   * // If you anticipate many results, you can end a stream early to prevent
1299 5
   * // unnecessary processing and API requests.
1300 5
   * //-
1301 5
   * instance.getDatabasesStream()
1302 5
   *   .on('data', function(database) {
1303 5
   *     this.end();
1304 5
   *   });
1305 5
   */
1306 5
  getDatabasesStream(options: GetDatabasesOptions = {}): NodeJS.ReadableStream {
1307 5
    const gaxOpts = extend(true, {}, options.gaxOptions);
1308 5

1309 5
    let reqOpts = extend({}, options, {
1310 5
      parent: this.formattedName_,
1311 5
    });
1312 5
    delete reqOpts.gaxOptions;
1313 5

1314 5
    // Copy over pageSize and pageToken values from gaxOptions.
1315 5
    // However values set on options take precedence.
1316 5
    if (gaxOpts) {
1317 5
      reqOpts = extend(
1318 5
        {},
1319 5
        {
1320 5
          pageSize: gaxOpts.pageSize,
1321 5
          pageToken: gaxOpts.pageToken,
1322 5
        },
1323 5
        reqOpts
1324 5
      );
1325 5
      delete gaxOpts.pageSize;
1326 5
      delete gaxOpts.pageToken;
1327 5
    }
1328 5

1329 5
    return this.requestStream({
1330 5
      client: 'DatabaseAdminClient',
1331 5
      method: 'listDatabasesStream',
1332 5
      reqOpts,
1333 5
      gaxOpts,
1334 5
      headers: this.resourceHeader_,
1335 5
    });
1336 5
  }
1337 5

1338 5
  getMetadata(
1339 5
    options?: GetInstanceMetadataOptions
1340 5
  ): Promise<GetInstanceMetadataResponse>;
1341 5
  getMetadata(callback: GetInstanceMetadataCallback): void;
1342 5
  getMetadata(
1343 5
    options: GetInstanceMetadataOptions,
1344 5
    callback: GetInstanceMetadataCallback
1345 5
  ): void;
1346 5
  /**
1347 5
   * @typedef {array} GetInstanceMetadataResponse
1348 5
   * @property {object} 0 The {@link Instance} metadata.
1349 5
   * @property {object} 1 The full API response.
1350 5
   */
1351 5
  /**
1352 5
   * @callback GetInstanceMetadataCallback
1353 5
   * @param {?Error} err Request error, if any.
1354 5
   * @param {object} metadata The {@link Instance} metadata.
1355 5
   * @param {object} apiResponse The full API response.
1356 5
   */
1357 5
  /**
1358 5
   * Get the instance's metadata.
1359 5
   *
1360 5
   * Wrapper around {@link v1.InstanceAdminClient#getInstance}.
1361 5
   *
1362 5
   * @see {@link v1.InstanceAdminClient#getInstance}
1363 5
   * @see [GetInstance API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.instance.v1#google.spanner.admin.instance.v1.InstanceAdmin.GetInstance)
1364 5
   *
1365 5
   * @param {GetInstanceMetadataOptions} [options] Configuration object
1366 5
   * @param {string | string[]} [options.fieldNames] A list of `Instance` field
1367 5
   *     names to be requested. Eligible values are: `name`, `displayName`,
1368 5
   *     `endpointUris`, `labels`, `config`, `nodeCount`, `state`.
1369 5
   * @param {GetInstanceMetadataCallback} [callback] Callback function.
1370 5
   * @returns {Promise<GetInstanceMetadataResponse>}
1371 5
   *
1372 5
   * @example
1373 5
   * const {Spanner} = require('@google-cloud/spanner');
1374 5
   * const spanner = new Spanner();
1375 5
   *
1376 5
   * const instance = spanner.instance('my-instance');
1377 5
   *
1378 5
   * instance.getMetadata(function(err, metadata, apiResponse) {});
1379 5
   *
1380 5
   * //-
1381 5
   * // Request only `displayName`.
1382 5
   * //-
1383 5
   * instance.getMetadata({fieldNames: 'displayName'}, (err, metadata, apiResponse) => {
1384 5
   *   // metadata will only contain value for `displayName`
1385 5
   *   const displayName = metadata['displayName'];
1386 5
   * })
1387 5
   *
1388 5
   * //-
1389 5
   * // Request multiple specific field names.
1390 5
   * //-
1391 5
   * instance.getMetadata({fieldNames: ['displayName', 'nodeCount']}, (err, metadata, apiResponse) => {
1392 5
   *   // metadata will only contain value for `displayName` and 'nodeCount'
1393 5
   *   const displayName = metadata['displayName'];
1394 5
   *   const nodeCount = metadata['nodeCount'];
1395 5
   * });
1396 5
   *
1397 5
   * //-
1398 5
   * // If the callback is omitted, we'll return a Promise.
1399 5
   * //-
1400 5
   * instance.getMetadata().then(function(data) {
1401 5
   *   const metadata = data[0];
1402 5
   *   const apiResponse = data[1];
1403 5
   * });
1404 5
   */
1405 5
  getMetadata(
1406 5
    optionsOrCallback?:
1407 5
      | GetInstanceMetadataOptions
1408 5
      | GetInstanceMetadataCallback,
1409 5
    cb?: GetInstanceMetadataCallback
1410 5
  ): Promise<GetInstanceMetadataResponse> | void {
1411 5
    const callback =
1412 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
1413 5
    const options =
1414 5
      typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
1415 5
    const reqOpts = {
1416 5
      name: this.formattedName_,
1417 5
    };
1418 5
    if (options.fieldNames) {
1419 5
      reqOpts['fieldMask'] = {
1420 5
        paths: arrify(options['fieldNames']!).map(snakeCase),
1421 5
      };
1422 5
    }
1423 5
    return this.request<IInstance>(
1424 5
      {
1425 5
        client: 'InstanceAdminClient',
1426 5
        method: 'getInstance',
1427 5
        reqOpts,
1428 5
        gaxOpts: options.gaxOptions,
1429 5
        headers: this.resourceHeader_,
1430 5
      },
1431 5
      (err, resp) => {
1432 5
        if (resp) {
1433 5
          this.metadata = resp;
1434 5
        }
1435 5
        callback!(err, resp);
1436 5
      }
1437 5
    );
1438 5
  }
1439 5

1440 5
  setMetadata(
1441 5
    metadata: IInstance,
1442 5
    gaxOptions?: CallOptions
1443 5
  ): Promise<SetInstanceMetadataResponse>;
1444 5
  setMetadata(metadata: IInstance, callback: SetInstanceMetadataCallback): void;
1445 5
  setMetadata(
1446 5
    metadata: IInstance,
1447 5
    gaxOptions: CallOptions,
1448 5
    callback: SetInstanceMetadataCallback
1449 5
  ): void;
1450 5
  /**
1451 5
   * Update the metadata for this instance. Note that this method follows PATCH
1452 5
   * semantics, so previously-configured settings will persist.
1453 5
   *
1454 5
   * Wrapper around {@link v1.InstanceAdminClient#updateInstance}.
1455 5
   *
1456 5
   * @see {@link v1.InstanceAdminClient#updateInstance}
1457 5
   * @see [UpdateInstance API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.instance.v1#google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstance)
1458 5
   *
1459 5
   * @param {object} metadata The metadata you wish to set.
1460 5
   * @param {object} [gaxOptions] Request configuration options, outlined here:
1461 5
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
1462 5
   * @param {SetInstanceMetadataCallback} [callback] Callback function.
1463 5
   * @returns {Promise<LongRunningOperationResponse>}
1464 5
   *
1465 5
   * @example
1466 5
   * const {Spanner} = require('@google-cloud/spanner');
1467 5
   * const spanner = new Spanner();
1468 5
   *
1469 5
   * const instance = spanner.instance('my-instance');
1470 5
   *
1471 5
   * const metadata = {
1472 5
   *   displayName: 'My Instance'
1473 5
   * };
1474 5
   *
1475 5
   * instance.setMetadata(metadata, function(err, operation, apiResponse) {
1476 5
   *   if (err) {
1477 5
   *     // Error handling omitted.
1478 5
   *   }
1479 5
   *
1480 5
   *   operation
1481 5
   *     .on('error', function(err) {})
1482 5
   *     .on('complete', function() {
1483 5
   *       // Metadata updated successfully.
1484 5
   *     });
1485 5
   * });
1486 5
   *
1487 5
   * //-
1488 5
   * // If the callback is omitted, we'll return a Promise.
1489 5
   * //-
1490 5
   * instance.setMetadata(metadata).then(function(data) {
1491 5
   *   const operation = data[0];
1492 5
   *   const apiResponse = data[1];
1493 5
   * });
1494 5
   */
1495 5
  setMetadata(
1496 5
    metadata: IInstance,
1497 5
    optionsOrCallback?: CallOptions | SetInstanceMetadataCallback,
1498 5
    cb?: SetInstanceMetadataCallback
1499 5
  ): void | Promise<SetInstanceMetadataResponse> {
1500 5
    const gaxOpts =
1501 5
      typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
1502 5
    const callback =
1503 5
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
1504 5

1505 5
    const reqOpts = {
1506 5
      instance: extend(
1507 5
        {
1508 5
          name: this.formattedName_,
1509 5
        },
1510 5
        metadata
1511 5
      ),
1512 5
      fieldMask: {
1513 5
        paths: Object.keys(metadata).map(snakeCase),
1514 5
      },
1515 5
    };
1516 5
    return this.request(
1517 5
      {
1518 5
        client: 'InstanceAdminClient',
1519 5
        method: 'updateInstance',
1520 5
        reqOpts,
1521 5
        gaxOpts,
1522 5
        headers: this.resourceHeader_,
1523 5
      },
1524 5
      callback!
1525 5
    );
1526 5
  }
1527 5
  /**
1528 5
   * Format the instance name to include the project ID.
1529 5
   *
1530 5
   * @private
1531 5
   *
1532 5
   * @param {string} projectId The project ID.
1533 5
   * @param {string} name The instance name.
1534 5
   * @returns {string}
1535 5
   *
1536 5
   * @example
1537 5
   * Instance.formatName_('grape-spaceship-123', 'my-instance');
1538 5
   * // 'projects/grape-spaceship-123/instances/my-instance'
1539 5
   */
1540 5
  static formatName_(projectId: string, name: string) {
1541 5
    if (name.indexOf('/') > -1) {
1542 5
      return name;
1543 5
    }
1544 5
    const instanceName = name.split('/').pop();
1545 5
    return 'projects/' + projectId + '/instances/' + instanceName;
1546 5
  }
1547 5
}
1548 5

1549 5
/*! Developer Documentation
1550 5
 *
1551 5
 * All async methods (except for streams) will return a Promise in the event
1552 5
 * that a callback is omitted.
1553 5
 */
1554 5
promisifyAll(Instance, {
1555 5
  exclude: ['database', 'backup'],
1556 5
});
1557 5

1558 5
/**
1559 5
 * Reference to the {@link Instance} class.
1560 5
 * @name module:@google-cloud/spanner.Instance
1561 5
 * @see Instance
1562 5
 */
1563 5
export {Instance};

Read our documentation on viewing source code .

Loading