All files column.ts

84.48% Statements 49/58
64.29% Branches 18/28
75% Functions 6/8
84.48% Lines 49/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                  6x 6x 6x 6x 6x 6x                             6x                               53x 53x 53x 53x 53x 53x 53x 53x 53x   53x 53x 53x 53x 53x 53x 53x 53x 53x                       6x 7x       7x       7x                       6x   40x 40x 40x   40x   40x     40x 7x   40x 13x   40x 6x   40x     40x     6x           6x     6x       6x                         6x     6x  
//todo: funcionamiento para tipo de columna boolean. Poder usar "true/false"
//todo: poder obtener una columna de la tabla de un modelo y hacerla nullable (para los casos en que
// se quiera hacer la columna fk nullable
//todo: hacer configurable politica de acciones: cascade, set null, etc.
 
import { DBtype } from './types';
import { TableBuilder } from 'knex';
import { InvalidColumnData } from './exceptions';
 
export const enum ColumnAction {
  Cascade = 'cascade',
  SetNull = 'set null',
  SetDefault = 'set default',
  Restrict = 'restrict',
  NoAction = 'no action'
}
 
export interface IColumn {
  name?: string;
  dbType?: DBtype | any;
  size?: number;
  foreignKey?: boolean;
  relatedTable?: string;
  unique?: boolean;
  defaultValue?: any;
  notNullable?: boolean;
  index?: boolean;
}
 
export class Column implements IColumn {
  name?: string;
  dbType?: DBtype;
  size?: number;
  foreignKey?: boolean;
  relatedTable?: string;
  unique?: boolean;
  defaultValue?: any;
  notNullable?: boolean;
  index?: boolean;
 
  //todo: sqlite no soporta default values (solo null) eliminar la opcion "defaultValue"
  //`sqlite` does not support inserting default values. Specify values explicitly or use the `useNullAsDefault`
  // config flag. (see docs http://knexjs.org/#Builder-insert).
 
  constructor({
    name,
    size,
    dbType,
    foreignKey,
    relatedTable,
    unique,
    defaultValue,
    notNullable,
    index
  }: IColumn) {
    this.name = name;
    this.dbType = dbType;
    this.foreignKey = foreignKey;
    this.relatedTable = relatedTable;
    this.unique = unique;
    this.defaultValue = defaultValue;
    this.size = size;
    this.notNullable = notNullable;
    this.index = index;
  }
 
  /**
   * Creates foreign key relation between two columns in two tables
   * Column 1: primary key column ('id')
   * Column 2: foreign key column (<modelName>_id)
   * Table 1: table
   * Table 2: this.relatedTable
   * Note: ColumnAction = 'Cascade' by default. Not configurable by now
   * @param {knex.TableBuilder} table
   */
  public createColumnsRelation(table: TableBuilder) {
    Iif (!this.name) {
      throw new InvalidColumnData(this.name);
    }
 
    Iif (!this.relatedTable) {
      throw new InvalidColumnData(this.relatedTable);
    }
 
    table
      .foreign(this.name)
      .references('id')
      .inTable(this.relatedTable)
      .onDelete(ColumnAction.Cascade)
      .onUpdate(ColumnAction.Cascade)
  }
 
  /**
   * Create table columns based in column properties
   * @param {Knex.TableBuilder} table
   */
  public createColumn(table: TableBuilder | any) {
    let newColumn;
    const colType = this.dbType;
    const colName = this.name;
    const colSize = this.size;
 
    this.size && console.warn('Size option exists for compatibility. It has no real effect');
 
    Iif (!colType || !colName) {
      throw new InvalidColumnData(colType || colName);
    }
    if (this.foreignKey) {
      this.createColumnsRelation(table);
    }
    if (this.notNullable) {
      newColumn = table[colType](colName).notNullable();
    }
    if (this.unique) {
      newColumn = Column.addUniqueConstraint(newColumn, table, colType, colName);
    }
    Iif (this.index) {
      newColumn = Column.addIndex(newColumn, table, colType, colName);
    }
    return newColumn || table[colType](colName, colSize);
  }
 
  private static addUniqueConstraint(
    newColumn: any,
    tableBuilder: TableBuilder | any,
    colType: DBtype,
    colName: string
  ): TableBuilder {
    Iif (newColumn) {
      return newColumn.unique();
    } else {
      return tableBuilder[colType](colName).unique();
    }
  }
 
  private static addIndex(
    newColumn: any,
    tableBuilder: TableBuilder | any,
    colType: DBtype,
    colName: string
  ): TableBuilder {
    if (newColumn) {
      return newColumn.index();
    } else {
      return tableBuilder[colType](colName).index();
    }
  }
 
  public isForeignKey(): boolean {
    return Boolean(this.foreignKey);
  }
}