garnet-database
Advanced tools
Comparing version 0.0.7 to 0.0.8
{ | ||
"name": "garnet-database", | ||
"version": "0.0.7", | ||
"version": "0.0.8", | ||
"description": "A library, which allows using Google Sheets as a database via Google Apps Script.", | ||
@@ -5,0 +5,0 @@ "main": "index.d.ts", |
/// <reference types="typings-google-apps-script" /> | ||
/// <reference path="util.ts" /> | ||
namespace Garnet { | ||
export namespace Database { | ||
export interface IEntity { | ||
__id?: string; | ||
} | ||
export interface IEntityConfiguration { | ||
mappings?: Array<IEntityMapping>; | ||
name: string; | ||
properties: Array<IEntityProperty>; | ||
} | ||
namespace Garnet { | ||
export interface IEntity { | ||
__id?: string; | ||
} | ||
export interface IEntityProperty { | ||
name: string; | ||
} | ||
export interface IEntityConfiguration { | ||
mappings?: Array<IEntityMapping>; | ||
name: string; | ||
properties: Array<IEntityProperty>; | ||
} | ||
export interface IEntityMapping { | ||
sourceProperty: string; | ||
targetConfig: IEntityConfiguration; | ||
targetProperty: string; | ||
mappingProperty: string; | ||
} | ||
export interface IEntityProperty { | ||
name: string; | ||
} | ||
module DatabaseManager { | ||
const __databases: { [key: string]: { [key: string]: Table<any> } } = {}; | ||
export interface IEntityMapping { | ||
sourceProperty: string; | ||
targetConfig: IEntityConfiguration; | ||
targetProperty: string; | ||
mappingProperty: string; | ||
} | ||
export function addTable<T extends IEntity>(spreadsheetId: string, table: Table<T>) { | ||
if (!__databases[spreadsheetId]) { | ||
__databases[spreadsheetId] = {}; | ||
} | ||
module DatabaseManager { | ||
const __databases: { [key: string]: { [key: string]: Table<any> } } = {}; | ||
__databases[spreadsheetId][table.getName()] = table; | ||
} | ||
export function addTable<T extends IEntity>(spreadsheetId: string, table: Table<T>) { | ||
if (!__databases[spreadsheetId]) { | ||
__databases[spreadsheetId] = {}; | ||
export function existsTable(spreadsheetId: string, tableName: string) { | ||
return __databases[spreadsheetId] && __databases[spreadsheetId][tableName]; | ||
} | ||
__databases[spreadsheetId][table.getName()] = table; | ||
export function getTable<T extends IEntity>(spreadsheetId: string, tableName: string): Table<T> { | ||
return __databases[spreadsheetId][tableName]; | ||
} | ||
} | ||
export function existsTable(spreadsheetId: string, tableName: string) { | ||
return __databases[spreadsheetId] && __databases[spreadsheetId][tableName]; | ||
} | ||
class Database { | ||
private __spreadsheet: GAS.Spreadsheet.Spreadsheet; | ||
export function getTable<T extends IEntity>(spreadsheetId: string, tableName: string): Table<T> { | ||
return __databases[spreadsheetId][tableName]; | ||
} | ||
} | ||
constructor(spreadsheetId: string) { | ||
this.__spreadsheet = SpreadsheetApp.openById(spreadsheetId); | ||
} | ||
class Database { | ||
private __spreadsheet: GAS.Spreadsheet.Spreadsheet; | ||
public newTable<T extends IEntity>(config: Garnet.Database.IEntityConfiguration): Table<T> { | ||
if (DatabaseManager.existsTable(this.__spreadsheet.getId(), config.name)) { | ||
return DatabaseManager.getTable<T>(this.__spreadsheet.getId(), config.name); | ||
} | ||
constructor(spreadsheetId: string) { | ||
this.__spreadsheet = SpreadsheetApp.openById(spreadsheetId); | ||
} | ||
public newTable<T extends IEntity>(config: Garnet.IEntityConfiguration): Table<T> { | ||
if (DatabaseManager.existsTable(this.__spreadsheet.getId(), config.name)) { | ||
return DatabaseManager.getTable<T>(this.__spreadsheet.getId(), config.name); | ||
let table = new Table<T>(this.__spreadsheet, config); | ||
DatabaseManager.addTable(this.__spreadsheet.getId(), table); | ||
return table; | ||
} | ||
let table = new Table<T>(this.__spreadsheet, config); | ||
DatabaseManager.addTable(this.__spreadsheet.getId(), table); | ||
return table; | ||
} | ||
} | ||
class Table<T extends IEntity> { | ||
private __sheet: GAS.Spreadsheet.Sheet; | ||
private __config: Garnet.IEntityConfiguration; | ||
class Table<T extends IEntity> { | ||
private __sheet: GAS.Spreadsheet.Sheet; | ||
private __config: Garnet.Database.IEntityConfiguration; | ||
constructor(private __spreadsheet: GAS.Spreadsheet.Spreadsheet, config: Garnet.IEntityConfiguration) { | ||
this.__config = JSON.parse(JSON.stringify(config)); | ||
this.__config.properties.unshift({ name: '__id' }); | ||
this.__sheet = __spreadsheet.getSheetByName(this.__config.name); | ||
} | ||
constructor(private __spreadsheet: GAS.Spreadsheet.Spreadsheet, config: Garnet.Database.IEntityConfiguration) { | ||
this.__config = JSON.parse(JSON.stringify(config)); | ||
this.__config.properties.unshift({ name: '__id' }); | ||
this.__sheet = __spreadsheet.getSheetByName(this.__config.name); | ||
} | ||
private __convertValuesToModel(data: Array<Array<any>>) { | ||
return data.map(row => createModel<T>(this.__config.properties.map(p => p.name), row)); | ||
} | ||
private __convertValuesToModel(data: Array<Array<any>>) { | ||
return data.map(row => createModel<T>(this.__config.properties.map(p => p.name), row)); | ||
} | ||
private __createMapping(data: Array<T>, mapping: IEntityMapping) { | ||
let mappingTable = DatabaseManager.getTable(this.__spreadsheet.getId(), mapping.targetConfig.name); | ||
let mappingData = mappingTable.getAllValues(); | ||
private __createMapping(data: Array<T>, mapping: IEntityMapping) { | ||
let mappingTable = DatabaseManager.getTable(this.__spreadsheet.getId(), mapping.targetConfig.name); | ||
let mappingData = mappingTable.getAllValues(); | ||
for (let value of data) { | ||
let mappedValue = mappingData.filter(el => el[mapping.targetProperty] == value[mapping.sourceProperty])[0]; | ||
value[mapping.mappingProperty] = mappedValue; | ||
for (let value of data) { | ||
let mappedValue = mappingData.filter(el => el[mapping.targetProperty] == value[mapping.sourceProperty])[0]; | ||
value[mapping.mappingProperty] = mappedValue; | ||
} | ||
} | ||
} | ||
private __convertModelToValueArray(model: T) { | ||
let result = []; | ||
for (let prop of this.__config.properties) { | ||
result.push(model[prop.name]); | ||
private __convertModelToValueArray(model: T) { | ||
let result = []; | ||
for (let prop of this.__config.properties) { | ||
result.push(model[prop.name]); | ||
} | ||
return result; | ||
} | ||
return result; | ||
} | ||
private __findLastRowIndex() { | ||
let spr = this.__sheet; | ||
let column = spr.getRange('A:A'); | ||
let values = column.getValues(); | ||
let ct = 0; | ||
while (values[ct][0] != "") { | ||
ct++; | ||
private __findLastRowIndex() { | ||
let spr = this.__sheet; | ||
let column = spr.getRange('A:A'); | ||
let values = column.getValues(); | ||
let ct = 0; | ||
while (values[ct][0] != "") { | ||
ct++; | ||
} | ||
return (ct); | ||
} | ||
return (ct); | ||
} | ||
private __findRowForId(id: string) { | ||
let values = this.__readValues(); | ||
let idx = Util.findIndex(values, el => el[0] == id); | ||
if (idx == -1) { | ||
throw new Error(`No value with id '${id}' found in table '${this.__config.name}'.`) | ||
private __findRowForId(id: string) { | ||
let values = this.__readValues(); | ||
let idx = Util.findIndex(values, el => el[0] == id); | ||
if (idx == -1) { | ||
throw new Error(`No value with id '${id}' found in table '${this.__config.name}'.`) | ||
} | ||
idx += 2; // Increment for missing header and row count starting at 1 | ||
return idx; | ||
} | ||
idx += 2; // Increment for missing header and row count starting at 1 | ||
return idx; | ||
} | ||
private __readValues() { | ||
let data = this.__sheet.getDataRange().getValues(); | ||
data.splice(0, 1); | ||
return data; | ||
} | ||
private __readValues() { | ||
let data = this.__sheet.getDataRange().getValues(); | ||
data.splice(0, 1); | ||
return data; | ||
} | ||
public getConfiguration() { | ||
return this.__config; | ||
} | ||
public getConfiguration() { | ||
return this.__config; | ||
} | ||
public getName() { | ||
return this.__config.name; | ||
} | ||
public getName() { | ||
return this.__config.name; | ||
} | ||
public deleteValue(id: string) { | ||
let emptyValues = []; | ||
for (let prop of this.__config.properties) { emptyValues.push('') }; | ||
public deleteValue(id: string) { | ||
let emptyValues = []; | ||
for (let prop of this.__config.properties) { emptyValues.push('') }; | ||
let rowIdx = this.__findRowForId(id); | ||
this.__sheet.getRange(rowIdx, 1, 1, this.__config.properties.length).setValues([emptyValues]); | ||
} | ||
let rowIdx = this.__findRowForId(id); | ||
this.__sheet.getRange(rowIdx, 1, 1, this.__config.properties.length).setValues([emptyValues]); | ||
} | ||
public getAllValues(): Array<T> { | ||
let values = this.__readValues().filter(row => row[0] && row[0] != ''); | ||
let models = this.__convertValuesToModel(values); | ||
public getAllValues(): Array<T> { | ||
let values = this.__readValues().filter(row => row[0] && row[0] != ''); | ||
let models = this.__convertValuesToModel(values); | ||
if (this.__config.mappings) { | ||
for (let mapping of this.__config.mappings) { | ||
this.__createMapping(models, mapping); | ||
if (this.__config.mappings) { | ||
for (let mapping of this.__config.mappings) { | ||
this.__createMapping(models, mapping); | ||
} | ||
} | ||
return models; | ||
} | ||
return models; | ||
} | ||
public insertValue(value: T) { | ||
let guid = Garnet.Util.generateGuid(); | ||
let valueArray = this.__convertModelToValueArray(value); | ||
valueArray[0] = guid; | ||
let rowIdx = this.__findLastRowIndex() + 1; | ||
this.__sheet.getRange(rowIdx, 1, 1, valueArray.length).setValues([valueArray]); | ||
return guid; | ||
} | ||
public insertValue(value: T) { | ||
let guid = Garnet.Util.generateGuid(); | ||
let valueArray = this.__convertModelToValueArray(value); | ||
valueArray[0] = guid; | ||
let rowIdx = this.__findLastRowIndex() + 1; | ||
this.__sheet.getRange(rowIdx, 1, 1, valueArray.length).setValues([valueArray]); | ||
return guid; | ||
} | ||
public updateValue(value: T) { | ||
if (!value.__id) { | ||
throw new Error('No __id provided for value update.'); | ||
public updateValue(value: T) { | ||
if (!value.__id) { | ||
throw new Error('No __id provided for value update.'); | ||
} | ||
let rowIdx = this.__findRowForId(value.__id); | ||
} | ||
let rowIdx = this.__findRowForId(value.__id); | ||
} | ||
} | ||
function createModel<T>(props: Array<string>, values: Array<any>): T { | ||
let result: any = {}; | ||
function createModel<T>(props: Array<string>, values: Array<any>): T { | ||
let result: any = {}; | ||
props.forEach((prop, idx) => { | ||
result[prop] = values[idx]; | ||
}); | ||
props.forEach((prop, idx) => { | ||
result[prop] = values[idx]; | ||
}); | ||
return result; | ||
} | ||
return result; | ||
} | ||
export function newDatabase(spreadsheetId: string) { | ||
return new Database(spreadsheetId); | ||
export function newDatabase(spreadsheetId: string) { | ||
return new Database(spreadsheetId); | ||
} | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
7739
166