UNPKG

qb-record

Version:

A lightweight abstraction layer for Quick Base

473 lines 16.9 kB
/*! * Package Name: qb-record * Package Description: A lightweight abstraction layer for Quick Base * Version: 5.0.23 * Build Timestamp: 2023-11-15T14:41:08.263Z * Package Homepage: https://github.com/tflanagan/node-qb-record * Git Location: git@github.com:tflanagan/node-qb-record.git * Authored By: Tristian Flanagan <contact@tristianflanagan.com> (https://github.com/tflanagan) * License: Apache-2.0 * * Copyright 2016 Tristian Flanagan * * 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. */ 'use strict'; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.replaceUndefinedWithString = exports.QBRecord = void 0; /* Dependencies */ const deepmerge_1 = __importDefault(require("deepmerge")); const rfc4122_1 = __importDefault(require("rfc4122")); const quickbase_1 = require("quickbase"); const qb_field_1 = require("qb-field"); /* Globals */ const VERSION = require('../package.json').version; const IS_BROWSER = typeof (window) !== 'undefined'; const rfc4122 = new rfc4122_1.default(); /* Main Class */ class QBRecord { constructor(options) { this.CLASS_NAME = 'QBRecord'; this._tableId = ''; this._fids = {}; this._fields = []; this._data = {}; this.id = rfc4122.v4(); const _a = options || {}, { quickbase } = _a, classOptions = __rest(_a, ["quickbase"]); if (quickbase_1.QuickBase.IsQuickBase(quickbase)) { this._qb = quickbase; } else { this._qb = new quickbase_1.QuickBase(deepmerge_1.default.all([ QBRecord.defaults.quickbase, quickbase || {} ])); } const settings = (0, deepmerge_1.default)(QBRecord.defaults, classOptions); this.setTableId(settings.tableId) .setFids(settings.fids) // @ts-ignore - my typescript skills fail me for now, tests are fine though .set('recordid', settings.recordid) // @ts-ignore - my typescript skills fail me for now, tests are fine though .set('primaryKey', settings.primaryKey); return this; } clear() { this._data = {}; this._fields = []; return this; } delete({ requestOptions } = {}) { return __awaiter(this, void 0, void 0, function* () { const recordid = this.get('recordid'); if (recordid) { const results = yield this._qb.deleteRecords({ tableId: this.getTableId(), where: `{'${this.getFid('recordid')}'.EX.'${recordid}'}`, requestOptions }); if (results.numberDeleted !== 0) { this.clear(); } return results; } else { this.clear(); return { numberDeleted: 0 }; } }); } get(field) { return this._data[field]; } getFid(field, byId = false) { const fids = this.getFids(); let id = -1; if (byId !== true) { if (fids.hasOwnProperty(field)) { id = fids[field]; } } else { id = ''; field = +field; Object.entries(fids).some(([name, fid]) => { if (fid === field) { id = name; return true; } return false; }); } return id; } getFids() { return this._fids; } getField(id, returnIndex = false) { const fields = this.getFields(); let result = undefined; for (let i = 0; result === undefined && i < fields.length; ++i) { if (fields[i].getFid() === id) { result = returnIndex ? i : fields[i]; } } return result; } getFields() { return this._fields; } getTableId() { return this._tableId; } getTempToken({ requestOptions } = {}) { return __awaiter(this, void 0, void 0, function* () { yield this._qb.getTempTokenDBID({ dbid: this.getTableId(), requestOptions }); }); } load({ clist, query, requestOptions } = {}) { return __awaiter(this, void 0, void 0, function* () { const where = []; let fids = this.getFids(); let select = []; if (query) { where.push(`(${query})`); } if (this.get('recordid')) { where.push(`{'${this.getFid('recordid')}'.EX.'${this.get('recordid')}'}`); } else if (this.get('primaryKey')) { where.push(`{'${this.getFid('primaryKey')}'.EX.'${this.get('primaryKey')}'}`); } if (clist) { if (typeof (clist) === 'string') { select = clist.split('.').map((val) => +val); } else { select = clist; } fids = select.reduce((fids, fid) => { let name = this.getFid(fid, true); if (!name) { name = fid; this.setFid(fid, fid); } fids[name] = fid; return fids; }, {}); } else { select = Object.entries(fids).map((fid) => { return fid[1]; }); } const results = yield this._qb.runQuery({ tableId: this.getTableId(), where: where.join('AND'), select: select, requestOptions }); results.fields.forEach((field) => { let result = this.getField(field.id); if (!result) { result = new qb_field_1.QBField({ quickbase: this._qb, tableId: this.getTableId(), fid: field.id }); this._fields.push(result); } Object.entries(field).forEach(([attribute, property]) => { result.set(attribute, property); }); }); if (results.metadata.totalRecords === 0) { throw new Error('Record not found'); } const record = results.data[0]; Object.entries(fids).forEach(([name, fid]) => { this.set(name, record[fid].value); }); return this._data; }); } loadSchema({ requestOptions } = {}) { return __awaiter(this, void 0, void 0, function* () { const results = yield this._qb.getFields({ tableId: this.getTableId(), requestOptions }); results.forEach((field) => { let result = this.getField(field.id); if (result === undefined) { result = new qb_field_1.QBField({ quickbase: this._qb, tableId: this.getTableId(), fid: field.id }); this._fields.push(result); } Object.entries(field).forEach(([property, value]) => { result.set(property, value); }); }); return this.getFields(); }); } save({ fidsToSave, mergeFieldId, requestOptions } = {}) { return __awaiter(this, void 0, void 0, function* () { const fids = this.getFids(); const names = Object.entries(fids).map(([name]) => name); const mergeField = mergeFieldId || this.getFid('primaryKey'); const { headers, data: results } = yield this._qb.upsert({ tableId: this.getTableId(), mergeFieldId: mergeField, data: [names.filter((name) => { const fid = fids[name]; const filtered = !fidsToSave || fidsToSave.indexOf(fid) !== -1 || fidsToSave.indexOf(name) !== -1 || fid === mergeField; if (!filtered) { return false; } const field = this.getField(fid); if (field && [ 'lookup', 'summary', 'formula' ].indexOf(field.get('mode') || '') !== -1) { return false; } return true; }).reduce((record, name) => { const fid = fids[name]; if (fid) { record[fid] = { value: (0, exports.replaceUndefinedWithString)(this.get(name)) }; } return record; }, {})], fieldsToReturn: names.map((name) => { return fids[name]; }).filter((val, i, arr) => { return arr.indexOf(val) === i; }), requestOptions, returnAxios: true }); const error = typeof (results.metadata.lineErrors) !== 'undefined' ? results.metadata.lineErrors[1] : false; if (error) { throw new quickbase_1.QuickBaseError(207, 'A partial success response was returned', error.join('\n'), headers['qb-api-ray']); } const record = results.data[0]; names.forEach((name) => { let value = undefined; const fid = fids[name]; if (fid) { const field = record[fid]; if (field) { value = field.value; } } this.set(name, value); }); return this._data; }); } set(field, value) { this._data[field] = value; return this; } setTableId(tableId) { this._tableId = tableId; return this; } setFid(name, id) { this._fids[name] = +id; return this; } setFids(fields) { Object.entries(fields).forEach(([name, fid]) => { this.setFid(name, fid); }); return this; } setFields(fields) { this._fields = fields; return this; } /** * Rebuild the QBRecord instance from serialized JSON * * @param json QBRecord serialized JSON */ fromJSON(json) { if (typeof (json) === 'string') { json = JSON.parse(json); } if (typeof (json) !== 'object') { throw new TypeError('json argument must be type of object or a valid JSON string'); } if (json.quickbase) { this._qb = new quickbase_1.QuickBase(json.quickbase); } if (json.tableId) { this.setTableId(json.tableId); } if (json.fids) { this.setFids(json.fids); } if (json.recordid) { // @ts-ignore - my typescript skills fail me for now, tests are fine though this.set('recordid', json.recordid); } if (json.primaryKey) { // @ts-ignore - my typescript skills fail me for now, tests are fine though this.set('primaryKey', json.primaryKey); } if (json.fields) { json.fields.forEach((fieldJSON) => { this._fields.push(qb_field_1.QBField.fromJSON(fieldJSON)); }); } if (json.data) { Object.entries(json.data).forEach(([property, value]) => { this.set(property, value); }); } return this; } /** * Serialize the QBRecord instance into JSON */ toJSON(fidsToConvert) { return { quickbase: this._qb.toJSON(), tableId: this.getTableId(), fids: this.getFids(), recordid: this.get('recordid'), primaryKey: this.get('primaryKey'), fields: this.getFields().map((field) => { return field.toJSON(); }), data: Object.entries(this._data).filter(([name]) => { return !fidsToConvert || fidsToConvert.indexOf(name) !== -1; }).reduce((data, [name, value]) => { data[name] = value; return data; }, {}) }; } /** * Create a new QBRecord instance from serialized JSON * * @param json QBRecord serialized JSON */ static fromJSON(json) { if (typeof (json) === 'string') { json = JSON.parse(json); } if (typeof (json) !== 'object') { throw new TypeError('json argument must be type of object or a valid JSON string'); } const newRecord = new QBRecord(); return newRecord.fromJSON(json); } /** * Test if a variable is a `qb-record` object * * @param obj A variable you'd like to test */ static IsQBRecord(obj) { return (obj || {}).CLASS_NAME === QBRecord.CLASS_NAME; } /** * Returns a new QBRecord instance built off of `options`, that inherits configuration data from the passed in `data` argument. * * @param options QBRecord instance options * @param data Quick Base Record data */ static NewRecord(options, data) { const newRecord = new QBRecord(options); if (data) { Object.entries(data).forEach(([property, value]) => { newRecord.set(property, value); }); } return newRecord; } ; } exports.QBRecord = QBRecord; QBRecord.CLASS_NAME = 'QBRecord'; QBRecord.VERSION = VERSION; /** * The default settings of a `QuickBase` instance */ QBRecord.defaults = { quickbase: { realm: IS_BROWSER ? window.location.host.split('.')[0] : '' }, tableId: (() => { if (IS_BROWSER) { const tableId = window.location.pathname.match(/^\/db\/(?!main)(.*)$/); if (tableId) { return tableId[1]; } } return ''; })(), fids: { recordid: 3, primaryKey: 3 }, recordid: undefined, primaryKey: undefined }; /* Helpers */ const replaceUndefinedWithString = (val) => { return val === null || val === undefined || (typeof val === 'number' && isNaN(val)) ? '' : val; }; exports.replaceUndefinedWithString = replaceUndefinedWithString; /* Export to Browser */ if (IS_BROWSER) { window.QBRecord = exports; } //# sourceMappingURL=qb-record.js.map