UNPKG

yekonga-server

Version:
552 lines (446 loc) 15.7 kB
// @ts-nocheck /*global Yekonga, serverLibrary */ const fs = serverLibrary.fs; const path = serverLibrary.path; const H = Yekonga.Helper; var migrationDir = null; var archivesDir = null; function initiateMigration() { if (!Yekonga.MigrationDB) { migrationDir = path.join(serverLibrary.__dirname, 'migration'); archivesDir = path.join(serverLibrary.__dirname, 'archives'); if (!fs.existsSync(migrationDir)) { fs.mkdirSync(migrationDir); } if (!fs.existsSync(archivesDir)) { fs.mkdirSync(archivesDir); } Yekonga.MigrationDB = Yekonga.DBbuilder({ type: 'nedb', tables: { migrations: { path: path.join(serverLibrary.__dirname, 'archives/migrations.db') } } }); } } class Migration { constructor(collection) { this.collection = collection; initiateMigration(); } static async load() { initiateMigration(); if (migrationDir) { var files = fs.readdirSync(migrationDir); var exists = await Yekonga.MigrationDB.table('migrations').lists('name'); for (const file of files) { if (!exists.includes(file)) { var result = null; console.info(`Start migration`, `migrating file => ${file}`); var response = (await require(path.join(migrationDir, file))); if (typeof response == 'function') { result = await response(file); } else { result = response; } if (typeof result == 'undefined') result = { data: { status: "SUCCESS" } }; if (!result || result.error) { console.error(`End migration`, `Error on migrating file => ${file}`); console.log(result); break; } else { console.info(`End migration`, `Success on migrating file => ${file}`); } } } } } } class MigrationBuilder { constructor(collection, action) { this.collection = collection; this.action = action; this.file = null; this.fields = {}; this.tables = []; } renameTable(name) { var table = new MigrationBuilderTable(this.collection); table.renameTo(name); this.tables.push(table); return table; } emptyTable() { var table = new MigrationBuilderTable(this.collection); table.empty(); this.tables.push(table); return table; } dropTable() { var table = new MigrationBuilderTable(this.collection); table.drop(); this.tables.push(table); return table; } setField(name, type = null, autoincrement = false) { var field = new MigrationBuilderField(name, type, autoincrement); return field; } increments(value, primaryKey = false) { var field = this.setField(value, 'int', true); field.increments().length(11); if (primaryKey) { field.primaryKey(); } this.fields[value] = field; return this.fields[value]; } bigIncrements(value, primaryKey = false) { var field = this.setField(value, 'bigInt', true); field.increments().length(24); if (primaryKey) { field.primaryKey(); } this.fields[value] = field; return this.fields[value]; } string(value, length = 248) { var field = this.setField(value, 'string'); field.length(length); this.fields[value] = field; return this.fields[value]; } text(value) { var field = this.setField(value, 'text'); field.nullable().default('NULL') this.fields[value] = field; return this.fields[value]; } longText(value) { var field = this.setField(value, 'longText'); this.fields[value] = field; return this.fields[value]; } float(value) { var field = this.setField(value, 'float'); this.fields[value] = field; return this.fields[value]; } double(value) { var field = this.setField(value, 'double'); this.fields[value] = field; return this.fields[value]; } decimal(value, length = '12,2') { var field = this.setField(value, 'double'); field.length(length); this.fields[value] = field; return this.fields[value]; } int(value, length = 11) { var field = this.setField(value, 'int'); field.length(length); this.fields[value] = field; return this.fields[value]; } bigInt(value) { var field = this.setField(value, 'bigInt'); this.fields[value] = field; return this.fields[value]; } tinyInt(value, length = 1) { var field = this.setField(value, 'tinyInt'); field.length(length); this.fields[value] = field; return this.fields[value]; } boolean(value) { var field = this.setField(value, 'boolean'); field.length(1); this.fields[value] = field; return this.fields[value]; } timestamp(value) { var field = this.setField(value, 'timestamp'); this.fields[value] = field; return this.fields[value]; } datetime(value) { var field = this.setField(value, 'datetime'); this.fields[value] = field; return this.fields[value]; } year(value) { var field = this.setField(value, 'year'); this.fields[value] = field; return this.fields[value]; } date(value) { var field = this.setField(value, 'date'); this.fields[value] = field; return this.fields[value]; } time(value) { var field = this.setField(value, 'time'); this.fields[value] = field; return this.fields[value]; } rename(arg1, arg2) { var field = this.setField(arg1); field.renameTo(arg2); this.fields[arg1] = field; return this.fields[arg1]; } drop(value) { var field = this.setField(value); field.drop(); this.fields[value] = field; return this.fields[value]; } getType(field) { var str = `VARCHAR(${field._length})`; switch (field._type) { case 'boolean': str = 'BOOLEAN'; break; case 'int': str = `INT(${field._length})`; break; case 'bigInt': str = `BIGINT(${field._length})`; break; case 'tinyInt': str = `TINYINT(${field._length})`; break; case 'float': str = `FLOAT`; break; case 'double': str = `DOUBLE`; break; case 'decimal': str = `DECIMAL(${field._length})`; break; case 'text': str = 'TEXT'; break; case 'longText': str = 'LONGTEXT'; break; case 'timestamp': str = 'TIMESTAMP'; break; case 'datetime': str = 'DATETIME'; break; case 'date': str = 'DATE'; break; case 'time': str = 'TIME'; break; case 'year': str = 'YEAR'; break; default: break; } return str; } async run() { var str = ''; if (H.tableActions.includes(this.action)) { for (const table of this.tables) { if (table._action == 'drop') { str += `DROP TABLE \`${table._name}\`;`; } else if (table._action == 'empty') { str += `TRUNCATE \`${table._name}\`;`; } else if (table._action == 'rename') { str += `RENAME TABLE \`${table._name}\` TO \`${table._renameTo}\`;`; } } } else { if (this.action == 'create') { str += `CREATE TABLE \`${this.collection}\` ( `; } else { str += `ALTER TABLE \`${this.collection}\` `; } var subStr = []; for (const key in this.fields) { if (this.fields.hasOwnProperty(key)) { const field = this.fields[key]; if (this.action == 'create') { var type = this.getType(field); var nullable = (field._nullable) ? 'NULL' : 'NOT NULL'; var comment = (field._comment) ? `COMMENT '${field._comment}'` : ``; var defaultValue = (typeof field._default != 'undefined') ? `${((field._default == 'AUTO_INCREMENT')? '':'DEFAULT')} ${((field._default == null)? 'NULL': field._default)}` : ''; subStr.push(`\`${field._name}\` ${type} ${nullable} ${defaultValue} ${comment}`); if (field._primaryKey) { subStr.push(`PRIMARY KEY (\`${field._name}\`)`); } if (field._unique && !field._primaryKey) { subStr.push(`UNIQUE (\`${field._name}\`)`); } if (field._index && !field._primaryKey && !field._unique) { subStr.push(`INDEX (\`${field._name}\`)`); } } else { if (field._drop) { subStr.push(`DROP \`${field._name}\``); } else { var action = (field._change) ? `CHANGE \`${field._name}\` \`${field._renameTo}\`` : `ADD \`${field._name}\``; var type = this.getType(field); var after = (field._after) ? `AFTER \`${field._after}\`` : ''; var first = (field._first) ? `${field._first}` : ''; var nullable = (field._nullable) ? 'NULL' : 'NOT NULL'; var comment = (field._comment) ? `COMMENT '${field._comment}'` : ``; var defaultValue = (typeof field._default != 'undefined') ? `${((field._default == 'AUTO_INCREMENT')? '':'DEFAULT')} ${((field._default == null)? 'NULL': field._default)}` : ''; if (field._type.includes('text') && field._name != field._renameTo) { subStr.push(`DROP INDEX \`${field._name}\``); } if (field._name != field._renameTo) { subStr.push(`${action} ${type} ${nullable} ${defaultValue} ${comment} ${after} ${first}`); } else { subStr.push(`${action} ${type} ${nullable} ${defaultValue} ${comment} ${after} ${first}`); } if (field._primaryKey) { subStr.push(`ADD PRIMARY KEY (\`${field._renameTo}\`)`); } if (field._unique && !field._primaryKey) { subStr.push(`ADD UNIQUE (\`${field._renameTo}\`)`); } if (field._index && !field._primaryKey && !field._unique) { subStr.push(`ADD INDEX (\`${field._renameTo}\`)`); } } } } } if (this.action == 'create') { str += subStr.join(', '); str += ` ) ENGINE = InnoDB;`; } else { for (const row of subStr) { str += `${row.trim()}, `; } str = str.trim().substr(0, (str.length - 2)) + ';'; } } var result = await Yekonga.DB.query(str); if (result.code && (result.code.includes('FIELD') || result.code.includes('ERROR'))) { return { error: result.code, message: result.sqlMessage, } } else if (result.error) { return result } else if (result.errors) { return { error: result.errors } } return { data: result } } } class MigrationBuilderTable { constructor(name) { this._name = name; this._renameTo = name; this._action = null; } renameTo(value) { this._renameTo = value; this._action = 'rename'; return this; } empty() { this._action = 'empty'; return this; } drop() { this._action = 'drop'; return this; } } class MigrationBuilderField { constructor(name, type, autoincrement) { this._name = name; this._type = type; this._autoincrement = autoincrement; this._renameTo = name; this._action = null; this._default = undefined; this._after = null; this._first = null; this._length = 248; this._index = false; this._unique = false; this._primaryKey = false; this._nullable = false; this._change = false; this._drop = false; this._comment = null; } renameTo(value) { this._renameTo = value; this.change(); return this; } index() { this._index = true; return this; } unique() { this._unique = true; return this; } primaryKey() { this._primaryKey = true; return this; } length(value) { this._length = value; return this; } nullable() { this._nullable = true; return this; } default (value) { this._default = value; if (value == null) { this.nullable(); } return this; } after(value) { this._after = value; return this; } first(value) { this._first = 'FIRST'; return this; } comment(value) { this._comment = value; return this; } increments() { this._default = 'AUTO_INCREMENT'; return this; } current() { this._default = 'CURRENT_TIMESTAMP'; return this; } change() { this._change = true; return this; } drop() { this._drop = true; return this; } } module.exports = { Migration, MigrationBuilder }