UNPKG

@google-cloud/bigtable

Version:
341 lines 9.91 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.Mutation = void 0; const arrify = require("arrify"); const is = require("is"); const Long = require("long"); /** * Formats table mutations to be in the expected proto format. * * @private * * @class * @param {object} mutation * * @example * ``` * const mutation = new Mutation({ * key: 'gwashington', * method: 'insert', * data: { * jadams: 1 * } * }); * ``` */ class Mutation { key; method; data; constructor(mutation) { this.key = mutation.key; this.method = mutation.method; this.data = mutation.data; } /** * Parses "bytes" returned from proto service. * * @param {string} bytes - Base64 encoded string. * @param {object} [options] Options to device return types * @param {boolean} [options.isPossibleNumber] Check if byte is number * @param {object} [options.userOptions] * @param {boolean} [options.userOptions.decode] Check if decode is required * @param {boolean} [options.userOptions.encoding] The encoding to use when * converting the buffer to a string. * @returns {string|number|buffer} * @private */ static convertFromBytes(bytes, options) { const buf = bytes instanceof Buffer ? bytes : Buffer.from(bytes, 'base64'); if (options && options.isPossibleNumber && buf.length === 8) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const num = Long.fromBytes(buf).toNumber(); if (Number.isSafeInteger(num)) { return num; } } const userOptions = (options && options.userOptions) || {}; if (userOptions.decode === false) { return buf; } return buf.toString(userOptions.encoding); } /** * Converts data into a buffer for proto service. * * @param {string} data - The data to be sent. * @returns {buffer} * @private */ static convertToBytes(data) { if (data instanceof Buffer) { return data; } if (is.number(data)) { return Buffer.from(Long.fromNumber(data).toBytesBE()); } try { return Buffer.from(data); } catch (e) { return data; } } /** * Takes date objects and creates a time range. * * @param {date} start - The start date. * @param {date} end - The end date. * @returns {object} * @private */ static createTimeRange(start, end) { const range = {}; if (is.date(start)) { range.startTimestampMicros = start.getTime() * 1000; } if (is.date(end)) { range.endTimestampMicros = end.getTime() * 1000; } return range; } /** * Formats an `insert` mutation to what the proto service expects. * * @param {object} data - The entity data. * @returns {object[]} * * @example * ``` * Mutation.encodeSetCell({ * follows: { * gwashington: 1, * alincoln: 1 * } * }); * // [ * // { * // setCell: { * // familyName: 'follows', * // columnQualifier: 'gwashington', // as buffer * // timestampMicros: -1, // -1 means to use the server time * // value: 1 // as buffer * // } * // }, { * // setCell: { * // familyName: 'follows', * // columnQualifier: 'alincoln', // as buffer * // timestampMicros: new Date(), // uses the client's current time * // value: 1 // as buffer * // } * // } * // ] * ``` * @private */ static encodeSetCell(data) { const mutations = []; Object.keys(data).forEach(familyName => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const family = data[familyName]; Object.keys(family).forEach(cellName => { let cell = family[cellName]; if (!is.object(cell) || cell instanceof Buffer) { cell = { value: cell, }; } let timestamp = cell.timestamp || new Date(); if (is.date(timestamp)) { timestamp = timestamp.getTime() * 1000; } const setCell = { familyName, columnQualifier: Mutation.convertToBytes(cellName), timestampMicros: timestamp, value: Mutation.convertToBytes(cell.value), }; mutations.push({ setCell }); }); }); return mutations; } /** * Formats a `delete` mutation to what the proto service expects. Depending * on what data is supplied to this method, it will return an object that can * will do one of the following: * * * Delete specific cells from a column. * * Delete all cells contained with a specific family. * * Delete all cells from an entire rows. * * @param {object} data - The entry data. * @returns {object} * * @example * ``` * Mutation.encodeDelete([ * 'follows:gwashington' * ]); * // { * // deleteFromColumn: { * // familyName: 'follows', * // columnQualifier: 'gwashington', // as buffer * // timeRange: null // optional * // } * // } * * Mutation.encodeDelete([ * 'follows' * ]); * // { * // deleteFromFamily: { * // familyName: 'follows' * // } * // } * * Mutation.encodeDelete(); * // { * // deleteFromRow: {} * // } * * // It's also possible to specify a time range when deleting specific * // columns. * * Mutation.encodeDelete([ * { * column: 'follows:gwashington', * time: { * start: new Date('March 21, 2000'), * end: new Date('March 21, 2001') * } * } * ]); * ``` * @private */ static encodeDelete(data) { if (!data) { return [ { deleteFromRow: {}, }, ]; } return arrify(data).map(mutation => { if (is.string(mutation)) { mutation = { column: mutation, }; } const column = Mutation.parseColumnName(mutation.column); if (!column.qualifier) { return { deleteFromFamily: { familyName: column.family, }, }; } let timeRange; if (mutation.time) { timeRange = Mutation.createTimeRange(mutation.time.start, mutation.time.end); } return { deleteFromColumn: { familyName: column.family, columnQualifier: Mutation.convertToBytes(column.qualifier), timeRange, }, }; }); } /** * Creates a new Mutation object and returns the proto JSON form. * * @param {object} mutation - The entity data. * @returns {object} * @private */ static parse(mutation) { if (!(mutation instanceof Mutation)) { mutation = new Mutation(mutation); } return mutation.toProto(); } /** * Parses a column name into an object. * * @param {string} column - The column name. * @returns {object} * * @example * ``` * Mutation.parseColumnName('follows:gwashington'); * // { * // family: 'follows', * // qualifier: 'gwashington' * // } * ``` * @private */ static parseColumnName(columnName) { const colonIdx = columnName.indexOf(':'); if (colonIdx === -1) { // columnName does not contain ':' return { family: columnName, qualifier: undefined, }; } return { family: columnName.slice(0, colonIdx), qualifier: columnName.slice(colonIdx + 1), }; } /** * Converts the mutation object into proto friendly JSON. * * @returns {object} * @private */ toProto() { const mutation = {}; if (this.key) { mutation.rowKey = Mutation.convertToBytes(this.key); } if (this.method === Mutation.methods.INSERT) { mutation.mutations = Mutation.encodeSetCell(this.data); } else if (this.method === Mutation.methods.DELETE) { mutation.mutations = Mutation.encodeDelete(this.data); } return mutation; } /** * Mutation methods * * @private * * INSERT => setCell * DELETE => deleteFrom* */ static methods = { INSERT: 'insert', DELETE: 'delete', }; } exports.Mutation = Mutation; //# sourceMappingURL=mutation.js.map