All files database.ts

52.54% Statements 31/59
66.67% Branches 8/12
53.85% Functions 7/13
51.72% Lines 30/58

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186    6x     6x                                                                                                                                                                                   6x   6x       6x 15x 15x 15x     238x 139x 139x     6x 141x 141x 111x   139x 139x     6x 2x 2x     6x 1x     6x 1x     6x 39x 39x     6x                                                           6x                           6x    
//todo: usar whatg-fetch en lugar de fetch para compatibilidad navegador (?)
 
const sql = require('sql.js');
import {QueryBuilder} from 'knex';
import {logQuery} from './yago.logger';
const FileSaver = require('file-saver');
 
declare const SQL: any;
 
//todo: falta completar definicion de tipos para clase Statement y documentar cada metodo
/** **************************************************************************************************************
 * db.js API
 * Documentation:
 * http://kripken.github.io/sql.js/documentation/#http://kripken.github.io/sql.js/documentation/class/Database.html
 **************************************************************************************************************** */
export interface db {
 
  /**
   * Open a new database either by creating a new one or opening an existing one,
   * stored in the byte array passed in first argument
   * @param {number[]} data
   */
  constructor(data: number[]): void;
 
  /**
   * Set DB created from external file
   * @param {db} database
   */
  setDatabase(database: db): void;
 
  /**
   * Runs a database query that can be created by the query builder or by a sql query string.
   * It does not return a list of results. It returns a "db" database object for fn chaining
   * It wraps db.run()
   * @param {Object | string} query
   */
  runQuery(query: QueryBuilder | string): any;
 
  /**
   * Execute a query against database and returns an array of objects
   * It wraps db.exec()
   * @param {QueryBuilder} query object
   * @returns {Object[]} List of models
   */
  execQuery(query: QueryBuilder | string): Object[];
 
  /**
   * Get the results from a query and transform them into a list of POJOs
   * @param statement Prepared SQL statement
   * @returns {Object[]}
   */
  getResults(statement: any): Object[];
 
  /**
   * Check whether a table exists in the database
   * @param {string} tableName
   * @returns {boolean}
   */
  hasTable(tableName: string): boolean;
 
  /**
   * Check databse integrity (for posible errors and corruption)
   * @returns {Object[]} with integrity info
   */
  integrityCheck(): Object[];
 
  /**
   * Get DDL (Data Definition Language) queries
   * Useful for debugging purposes
   * @return {Object[]}
   */
  getSchema(): Object[];
 
  /**
   * Get id of last record inserted in database
   * @return {number}
   */
  getIdLastRecordInserted(): number;
 
  run(sqlQuery: string, params?: object | any[]): db;
  exec(sqlQuery: string): Array<{columns: string[], values: any[]}>;
  prepare(sqlQuery: string, params?: object | any[]): Object;
  each(sqlQuery: string, callback: Function, done: Function, params?: object | any[]): db;
  export(): Uint8Array;
  close(): void;
  getRowsModified(): number;
  create_function(name: string, fn: Function): void;
}
 
 
 
/**
 * Database instance
 * @type {SQL} Global variable created by 'sql.js'
 */
export let db = new sql.Database();
 
db.__proto__.setDatabase = (database: any) => {
  db = database;
};
 
db.__proto__.runQuery = (query: QueryBuilder | string): any => {
  const queryString = query.toString();
  logQuery(queryString, 'query');
  return db.run(queryString);
};
 
db.__proto__.execQuery = (query: QueryBuilder | string, useLogger: boolean = true): Object[] => {
  useLogger && logQuery(query.toString(), 'query');
  return db.getResults( db.prepare(query.toString()) );
};
 
db.__proto__.getResults = (statement: any): Object[] => {
  let result: any[] = [];
  while (statement.step()){
    result.push(statement.getAsObject());
  }
  statement.free();
  return result;
};
 
db.__proto__.hasTable = (tableName: string): boolean => {
  const result = db.exec( `SELECT name FROM sqlite_master WHERE type='table' AND name='${tableName}'` );
  return result && result.length > 0
};
 
db.__proto__.integrityCheck = (): Object[] => {
  return db.execQuery('PRAGMA integrity_check', false);
};
 
db.__proto__.getSchema = () => {
  return db.execQuery('SELECT "name", "sql" FROM "sqlite_master" WHERE type="table"');
};
 
db.__proto__.getIdLastRecordInserted = (): number => {
  const result = db.execQuery('SELECT last_insert_rowid()', false);
  return result && result[0]['last_insert_rowid()'];
};
 
export const loadDbFromFile = (fileNamePath: string, actionFn: Function): void => {
  fetch(fileNamePath)
    .then((response: any) => {
      if (response) {
        return response.arrayBuffer();
      }
    }).then((arrayBuffer: any) => {
    if (arrayBuffer) {
      const dbFile = new Uint8Array(arrayBuffer);
      const dbInstance = new SQL.Database(dbFile);
      db.setDatabase(dbInstance);
      try {
        db.integrityCheck();
      } catch (error) {
        console.error(error);
        alert(`Error loading db file: "${fileNamePath}"`);
      }
      console.clear();
      const logFormat = 'background: cornflowerblue; color: white; font-weight: ';
      console.log(`%c Database loaded from file "${fileNamePath}" `, logFormat);
      db.execQuery('PRAGMA foreign_keys=ON;');
      actionFn();
    }
  })
  .catch((error: Error) => {
    console.error(error);
    alert('Error loading db file');
  })
};
 
export const saveDbToFile = (fileNamePath: string) => {
  try {
    const isFileSaverSupported = !!new Blob;
    const uint8Array = db.export();
    const buffer = new Buffer(uint8Array);
    const file = new File([buffer], fileNamePath, {type: 'application/octet-stream'});
    FileSaver.saveAs(file);
  } catch (exception) {
    alert('Save file to disk not supported by browser');
    console.error(exception);
  }
  db.execQuery('PRAGMA foreign_keys=ON;');
};
 
console.clear();