family.js

"use strict";
/*!
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
const promisify_1 = require("@google-cloud/promisify");
/**
 * @private
 */
class FamilyError extends Error {
    constructor(name) {
        super();
        this.name = 'FamilyError';
        this.message = `Column family not found: ${name}.`;
        this.code = 404;
    }
}
exports.FamilyError = FamilyError;
/**
 * Create a Family object to interact with your table column families.
 *
 * @class
 * @param {Table} table
 * @param {string} id
 *
 * @example
 * const Bigtable = require('@google-cloud/bigtable');
 * const bigtable = new Bigtable();
 * const instance = bigtable.instance('my-instance');
 * const table = instance.table('prezzy');
 * const family = table.family('follows');
 */
class Family {
    constructor(table, id) {
        this.bigtable = table.bigtable;
        this.table = table;
        let name;
        if (id.includes('/')) {
            if (id.startsWith(`${table.name}/columnFamilies/`)) {
                name = id;
            }
            else {
                throw new Error(`Family id '${id}' is not formatted correctly.
Please use the format 'follows' or '${table.name}/columnFamilies/my-family'.`);
            }
        }
        else {
            name = `${table.name}/columnFamilies/${id}`;
        }
        this.name = name;
        this.id = name.split('/').pop();
    }
    /**
     * Formats Garbage Collection rule into proto format.
     *
     * @private
     *
     * @param {object} ruleObj The rule object.
     * @returns {object}
     *
     * @example
     * Family.formatRule({
     *   age: {
     *     seconds: 10000,
     *     nanos: 10000
     *   },
     *   versions: 2,
     *   union: true
     * });
     * // {
     * //   union: {
     * //     rules: [
     * //       {
     * //         maxAge: {
     * //           seconds: 10000,
     * //           nanos: 10000
     * //         }
     * //       }, {
     * //         maxNumVersions: 2
     * //       }
     * //     ]
     * //   }
     * // }
     */
    static formatRule_(ruleObj) {
        const rules = [];
        if (ruleObj.age) {
            rules.push({
                maxAge: ruleObj.age,
            });
        }
        if (ruleObj.versions) {
            rules.push({
                maxNumVersions: ruleObj.versions,
            });
        }
        if (ruleObj.rule) {
            rules.push(Family.formatRule_(ruleObj.rule));
        }
        if (rules.length === 1) {
            if (ruleObj.union) {
                throw new Error('A union must have more than one garbage collection rule.');
            }
            return rules[0];
        }
        if (rules.length === 0) {
            throw new Error('No garbage collection rules were specified.');
        }
        const rule = {};
        const ruleType = ruleObj.union ? 'union' : 'intersection';
        rule[ruleType] = {
            rules,
        };
        return rule;
    }
    /**
     * Create a column family.
     *
     * @param {object} [options] See {@link Table#createFamily}.
     * @param {function} callback The callback function.
     * @param {?error} callback.err An error returned while making this
     *     request.
     * @param {Family} callback.family The metadata.
     * @param {object} callback.apiResponse The full API response.
     *
     * @example <caption>include:samples/document-snippets/family.js</caption>
     * region_tag:bigtable_create_family
     */
    create(options, callback) {
        callback = typeof options === 'function' ? options : callback;
        options = typeof options === 'object' ? options : {};
        this.table.createFamily(this.id, options, callback);
    }
    /**
     * Delete the column family.
     *
     * @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/document-snippets/family.js</caption>
     * region_tag:bigtable_del_family
     */
    delete(gaxOptions, callback) {
        callback = typeof gaxOptions === 'function' ? gaxOptions : callback;
        gaxOptions = typeof gaxOptions === 'object' ? gaxOptions : {};
        this.bigtable.request({
            client: 'BigtableTableAdminClient',
            method: 'modifyColumnFamilies',
            reqOpts: {
                name: this.table.name,
                modifications: [
                    {
                        id: this.id,
                        drop: true,
                    },
                ],
            },
            gaxOpts: gaxOptions,
        }, callback);
    }
    /**
     * Check if the column family 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 family exists or not.
     *
     * @example <caption>include:samples/document-snippets/family.js</caption>
     * region_tag:bigtable_exists_family
     */
    exists(opts, cb) {
        const callback = typeof opts === 'function' ? opts : cb;
        const gaxOptions = typeof opts === 'object' ? opts : {};
        this.getMetadata(gaxOptions, err => {
            if (err) {
                if (err instanceof FamilyError) {
                    callback(null, false);
                    return;
                }
                callback(err);
                return;
            }
            callback(null, true);
        });
    }
    /**
     * Get a column family if it exists.
     *
     * You may optionally use this to "get or create" an object by providing an
     * object with `autoCreate` set to `true`. Any extra configuration that is
     * normally required for the `create` method must be contained within this
     * object as well.
     *
     * @param {object} [options] Configuration object.
     * @param {boolean} [options.autoCreate=false] Automatically create the
     *     instance if it does not already exist.
     * @param {object} [options.gaxOptions] Request configuration options, outlined
     *     here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
     * @param {?error} callback.error An error returned while making this request.
     * @param {Family} callback.family The Family object.
     * @param {object} callback.apiResponse The resource as it exists in the API.
     *
     * @example <caption>include:samples/document-snippets/family.js</caption>
     * region_tag:bigtable_get_family
     */
    get(opts, cb) {
        const callback = typeof opts === 'function' ? opts : cb;
        const options = typeof opts === 'object' ? opts : {};
        const autoCreate = !!options.autoCreate;
        const gaxOptions = options.gaxOptions;
        this.getMetadata(gaxOptions, (err, metadata) => {
            if (err) {
                if (err instanceof FamilyError && autoCreate) {
                    this.create({ gaxOptions, rule: options.rule }, callback);
                    return;
                }
                callback(err);
                return;
            }
            callback(null, this, metadata);
        });
    }
    /**
     * Get the column family's 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/document-snippets/family.js</caption>
     * region_tag:bigtable_get_family_meta
     */
    getMetadata(opts, cb) {
        const callback = typeof opts === 'function' ? opts : cb;
        const gaxOptions = typeof opts === 'object' ? opts : {};
        this.table.getFamilies(gaxOptions, (err, families) => {
            if (err) {
                callback(err);
                return;
            }
            for (let i = 0, l = families.length; i < l; i++) {
                if (families[i].name === this.name) {
                    this.metadata = families[i].metadata;
                    callback(null, this.metadata);
                    return;
                }
            }
            const error = new FamilyError(this.id);
            callback(error);
        });
    }
    /**
     * Set the column family's metadata.
     *
     * See {@link Table#createFamily} for a detailed explanation of the
     * arguments.
     *
     * @see [Garbage Collection Proto Docs]{@link https://github.com/googleapis/googleapis/blob/3592a7339da5a31a3565870989beb86e9235476e/google/bigtable/admin/table/v1/bigtable_table_data.proto#L59}
     *
     * @param {object} metadata Metadata object.
     * @param {object} [metadata.rule] Garbage collection rule.
     * @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/document-snippets/family.js</caption>
     * region_tag:bigtable_set_family_meta
     */
    setMetadata(metadata, opts, cb) {
        const callback = typeof opts === 'function' ? opts : cb;
        const gaxOptions = typeof opts === 'object' ? opts : {};
        const mod = {
            id: this.id,
            update: {},
        };
        if (metadata.rule) {
            mod.update.gcRule = Family.formatRule_(metadata.rule);
        }
        const reqOpts = {
            name: this.table.name,
            modifications: [mod],
        };
        this.bigtable.request({
            client: 'BigtableTableAdminClient',
            method: 'modifyColumnFamilies',
            reqOpts,
            gaxOpts: gaxOptions,
        }, (err, resp) => {
            if (err) {
                callback(err, null, resp);
                return;
            }
            this.metadata = resp.columnFamilies[this.id];
            callback(null, this.metadata, resp);
        });
    }
}
exports.Family = Family;
/*! Developer Documentation
 *
 * All async methods (except for streams) will return a Promise in the event
 * that a callback is omitted.
 */
promisify_1.promisifyAll(Family);
//# sourceMappingURL=family.js.map