Skip to content

Commit

Permalink
add function to get table data
Browse files Browse the repository at this point in the history
  • Loading branch information
rahul-jha98 committed Dec 29, 2020
1 parent beed8ed commit 66dad81
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 57 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "1.0.0",
"description": "Library to help use a Google Sheet as a database",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"start": "tsc && node lib/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
Expand Down
14 changes: 6 additions & 8 deletions src/dbhelper/Database.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import axios, {AxiosInstance, AxiosRequestConfig} from 'axios';
import {JWT} from 'google-auth-library';
import ACTIONS from './actions';
import {ACTIONS} from './actions';
import {Sheet} from './ResponseStructure';
import Table from './Table';
import {Table} from './Table';

const AUTH_MODE = {
ACCESS_TOKEN: 1,
Expand All @@ -21,7 +21,7 @@ const GOOGLE_AUTH_SCOPES = [
// 'https://www.googleapis.com/auth/spreadsheets.readonly',
];

class Database {
export class Database {
sheetId: string;

_tables: Record<number, Table> = {};
Expand Down Expand Up @@ -79,10 +79,10 @@ class Database {
}
}

async loadData() {
async loadData(withData: boolean = true) {
const response = await this.axios.get('/', {
params: {
includeGridData: true,
includeGridData: withData,
},
});
response.data.sheets.forEach((s: Sheet) => {
Expand Down Expand Up @@ -193,7 +193,7 @@ class Database {

// allow it to work with `.headers` but `.headerValues` is the real prop
if (headerValues || headers) {
await newSheet.setTableHeaders(headerValues || headers);
await newSheet.setColumnNames(headerValues || headers);
}

return newSheet;
Expand Down Expand Up @@ -255,5 +255,3 @@ class Database {
sheets.forEach((s: Sheet) => this._updateOrCreateTable(s));
}
}

export default Database;
82 changes: 57 additions & 25 deletions src/dbhelper/Table.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
import {columnNumberToName} from './utils';
import type Database from './Database';
import type {Database} from './Database';
import {Sheet, SheetData, SheetProperties} from './ResponseStructure';

export default class Table {
type primitiveTypes = string | boolean | number | null;

export class Table {
_database: Database;
_properties: SheetProperties;
_cells: (string|number|boolean|null)[][];
headerValues: string[];
_cells: (primitiveTypes)[][];
columnNames: string[];
lastRowWithValues: number;

constructor(database: Database, {properties, data}: Sheet) {
this._database = database;
this._properties = properties;

this._cells = [];
this.headerValues = [];
this.columnNames = [];

if (data) this._fillTableData(data);
}

_fillTableData(dataRanges: Array<SheetData>) {
dataRanges.forEach((range: SheetData) => {

const numRows = range.rowMetadata.length;
const numColumns = range.columnMetadata.length;
const numRows = this.rowCount;
const numColumns = this.columnCount;

for (let row = 0; row < numRows; row++) {
for (let column = 0; column < numColumns; column++) {
Expand All @@ -33,7 +36,7 @@ export default class Table {
range.rowData[row] &&
range.rowData[row].values[column]
) {

this.lastRowWithValues = row;
const cellValue = range.rowData[row].values[column].effectiveValue;
this._cells[row][column] = cellValue.numberValue || cellValue.stringValue || cellValue.boolValue;
}
Expand Down Expand Up @@ -109,15 +112,20 @@ export default class Table {
}


async loadTableHeaders() {
async loadColumnNames(silent:boolean= false) {

const rows = await this.getCellsInRange(`A1:${this.lastColumnLetter}1`);
if (!rows) {
if (silent)
return;
throw new Error('Table Headers (Header Row) is missing.');
}
console.log(rows[0]);
this.headerValues = rows[0].map((header: string) => header.trim());
this.columnNames = rows[0].map((header: string) => header.trim());

if (!this.headerValues.filter(Boolean).length) {
if (!this.columnNames.filter(Boolean).length) {
if (silent)
return;
throw new Error('All table headers are empty');
}
}
Expand All @@ -142,7 +150,7 @@ export default class Table {
* Updates the header values in the sheet
* @param {Array.<string>} headerValues Name of header values to be set
*/
async setTableHeaders(headerValues: string[]) {
async setColumnNames(headerValues: string[]) {
if (!headerValues) return;

if (headerValues.length > this.columnCount) {
Expand Down Expand Up @@ -179,7 +187,7 @@ export default class Table {
],
},
});
this.headerValues = response.data.updatedData.values[0];
this.columnNames = response.data.updatedData.values[0];

for (let i = 0; i < headerValues.length; i++) {
this._cells[0][i] = headerValues[i];
Expand All @@ -201,16 +209,17 @@ export default class Table {
return this._database.updateSheetProperties(this.sheetId, {title: newName});
}

async insertRows(rowValueArray) {
const rowsArray = []
async insertMany(rowValueArray, refetch: boolean = true) {
const rowsArray: primitiveTypes[][] = []

rowValueArray.forEach((row) => {
let rowAsArray;
if (Array.isArray(row)) {
rowAsArray = row;
} else if (typeof row === 'object' && row != null) {
rowAsArray = []
for(let i = 0; i < this.headerValues.length; i++) {
const columnName = this.headerValues[i];
for(let i = 0; i < this.columnNames.length; i++) {
const columnName = this.columnNames[i];
rowAsArray[i] = row[columnName];
}
} else {
Expand All @@ -219,32 +228,55 @@ export default class Table {
rowsArray.push(rowAsArray);
});

return this._addRows(rowsArray);
return this._addRows(rowsArray, refetch = refetch);

}
async insertRow(rowValue: Array<any>|Object) {
return this.insertRows([rowValue]);
async insertOne(rowValue: Array<primitiveTypes>|Object, refetch:boolean = true) {
return this.insertMany([rowValue], refetch=refetch);
}

async insert(rowValue, refetch: boolean = true) {
if (Array.isArray(rowValue)) {
if (Array.isArray(rowValue[0]) || (typeof rowValue[0] === 'object' && rowValue[0] != null)) {
return this.insertMany(rowValue, refetch);
}
}
return this.insertMany([rowValue], refetch)
}

async _addRows(rowsArrays: any[][], insert: boolean = false) {
async _addRows(rowsArrays: primitiveTypes[][],
refetch: boolean = true,
insert: boolean = false) {
console.log(insert, refetch);
if (!Array.isArray(rowsArrays)) throw new Error('Row values needs to be an array');

if (!this.headerValues) await this.loadTableHeaders();
if (!this.columnNames) await this.loadColumnNames();

const response = await this._database.axios.request({
await this._database.axios.request({
method: 'post',
url: `/values/${this.encodedA1SheetName}!A1:append`,
params: {
valueInputOption: 'RAW',
insertDataOption: insert ? 'INSERT_ROWS' : 'OVERWRITE',
includeValuesInResponse: true,
},
data: {
values: rowsArrays,
},
});

// if new rows were added, we need update sheet.rowRount
await this.loadCells();
console.log("Inserted Values");
if (refetch) {
console.log("Fetching")
await this.loadCells();
}
}

getDataAsArray() : primitiveTypes[][] {
return this._cells.slice(1, this.lastRowWithValues + 1);
}

async getData() {

}
}
5 changes: 2 additions & 3 deletions src/dbhelper/actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const ACTIONS = {
export const ACTIONS = {
TABLE_DELETED: 1,
TABLE_RENAMED: 2
}
export default ACTIONS;
}
29 changes: 8 additions & 21 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import Database from './dbhelper/Database';
import ACTIONS from './dbhelper/actions';
import type Table from './dbhelper/Table';
import creds from './creds.json';
import {Database} from './dbhelper/Database';
import {ACTIONS} from './dbhelper/actions';
import type {Table} from './dbhelper/Table';

export default class SheetDatabase {
export class SheetDatabase {
db: Database;
[key: string]: any;

Expand Down Expand Up @@ -49,10 +48,10 @@ export default class SheetDatabase {
/**
* Load the data of tables from sheet into memory
*/
async fetchTables() {
await this.db.loadData();
async fetchTables(loadTableData: boolean = true) {
await this.db.loadData(loadTableData);
for (const table of Object.values(this.db.tables)) {
await table.loadTableHeaders();
await table.loadColumnNames(true);
this[table.title] = table;
}
}
Expand Down Expand Up @@ -84,7 +83,7 @@ export default class SheetDatabase {
},
headerValues: columnNames,
});
await table.loadTableHeaders();
await table.loadColumnNames();
this[table.title] = table;
}

Expand All @@ -106,15 +105,3 @@ export default class SheetDatabase {
}

}

async function test() {
const dat = new SheetDatabase('1nwIJ9lLyivfsAlRBnkxl7Su7tCBo6tVsW9zwVCdTfsU');
dat.useServiceAccount(creds.client_email, creds.private_key);
await dat.fetchTables();

await dat.getTable('test4').insertRow(['string1', 1]);
await dat['test4'].insertRow({'id': 2, 'name': 'string2'});
console.log(dat.test4._cells);
}

test();

0 comments on commit 66dad81

Please sign in to comment.