nodejs-schema-rules
Version:
The CLI tool automatically generates basic validation rules for popular libraries such as JOI, ValidatorJS and @vinejs/vine based on your database table schema!
157 lines (156 loc) • 7.35 kB
JavaScript
;
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchemaOperationForMysql = void 0;
const messages_1 = require("../utils/messages");
const MySQLDatabase_1 = require("../databases/MySQLDatabase");
class SchemaOperationForMysql {
constructor(table, databaseConfig, selectedColumns, skipColumns) {
this.integerTypes = {
tinyint: {
unsigned: { min: '0', max: '255' },
signed: { min: '-128', max: '127' },
},
smallint: {
unsigned: { min: '0', max: '65535' },
signed: { min: '-32768', max: '32767' },
},
mediumint: {
unsigned: { min: '0', max: '16777215' },
signed: { min: '-8388608', max: '8388607' },
},
int: {
unsigned: { min: '0', max: '4294967295' },
signed: { min: '-2147483648', max: '2147483647' },
},
bigint: {
unsigned: { min: '0', max: '18446744073709551615' },
signed: { min: '-9223372036854775808', max: '9223372036854775807' },
},
year: {
//YEAR data type in MySQL allows representation of years in the range '0000' to '2155' and '1901'
min: '1901',
max: '2155',
},
timestamp: {
//the timestamp range for the TIMESTAMP data type in MySQL is from '1970-01-01 00:00:01' to '2038-01-19 03:14:07'
min: '1970-01-01 00:00:01',
max: '2038-01-19 03:14:07',
},
};
this.table = table;
this.databaseConfig = databaseConfig;
this.database = new MySQLDatabase_1.MySQLDatabase(this.databaseConfig);
this.selectedColumns = selectedColumns;
this.skipColumns = skipColumns;
}
getTableSchema() {
var _a;
return __awaiter(this, void 0, void 0, function* () {
yield this.database.connect();
let schema = [];
try {
const tableExist = yield this.database.query(`SHOW TABLES LIKE '${this.table}';`);
if (!tableExist.length) {
throw new Error((0, messages_1.warningMessage)(`The ${String(this.table)} table is not exist!`));
}
schema = (_a = (yield this.database.query(`SHOW COLUMNS FROM ${String(this.table)}`))) !== null && _a !== void 0 ? _a : [];
}
catch (error) {
console.error(error.message);
}
finally {
// Close the database connection
yield this.database.end();
}
return schema;
});
}
generateColumnRules() {
return __awaiter(this, void 0, void 0, function* () {
const rules = {};
let tableSchema = yield this.getTableSchema();
if (this.skipColumns.length || this.selectedColumns.length) {
tableSchema = tableSchema.filter(({ Field }) => {
return this.selectedColumns.length
? this.selectedColumns.includes(Field)
: !this.skipColumns.includes(Field);
});
}
tableSchema.forEach(({ Field, Type, Null, Key, Default, Extra }) => {
if (Extra === 'auto_increment') {
return;
}
let columnRules = [];
let type = Type;
switch (true) {
case type === 'tinyint(1)':
columnRules.push('boolean');
break;
case type.includes('char'):
columnRules.push('string');
columnRules.push('max:' + parseInt(type.replace(/\D/g, ''), 10));
break;
case type === 'text':
columnRules.push('string');
break;
case type.includes('int'):
columnRules.push('integer');
const sign = type.includes('unsigned') ? 'unsigned' : 'signed';
let intType = type.split(' unsigned')[0];
intType = intType.replace(/\([^)]+\)/, '');
if (!this.integerTypes[intType]) {
intType = 'int';
}
columnRules.push('min:' + this.integerTypes[intType][sign].min);
columnRules.push('max:' + this.integerTypes[intType][sign].max);
break;
case type.includes('double') ||
type.includes('decimal') ||
type.includes('dec') ||
type.includes('float'):
columnRules.push('numeric');
break;
case type.includes('enum') || type.includes('set'):
const matches = type
.match(/'([^']*)'/g)
.map((match) => match.slice(1, -1));
columnRules.push('string');
columnRules.push('in:' + matches.join(','));
break;
case type.includes('year'):
columnRules.push('integer');
columnRules.push('min:' + this.integerTypes.year.min);
columnRules.push('max:' + this.integerTypes.year.max);
break;
case type.includes('date') || type === 'time':
columnRules.push('date');
break;
case type === 'timestamp':
columnRules.push('date');
columnRules.push('after_or_equal:' + this.integerTypes.timestamp.min);
columnRules.push('before_or_equal:' + this.integerTypes.timestamp.max);
break;
case type === 'json':
columnRules.push('json');
break;
default:
// Skip for other type like Binary,Bit and Spatial Types
break;
}
columnRules.push(Null === 'YES' ? 'nullable' : 'required');
rules[Field] = columnRules;
});
return rules;
});
}
}
exports.SchemaOperationForMysql = SchemaOperationForMysql;