Comparing version 1.0.0-alpha.1 to 1.0.0-alpha.2
@@ -16,3 +16,3 @@ #!/usr/bin/env node | ||
const fs = require('fs'); | ||
const assert = require('assert'); | ||
const path = require('path'); | ||
@@ -22,2 +22,4 @@ const sqb = require('sqb'); | ||
const appdir = path.resolve(__dirname, '..'); | ||
function logError(args) { | ||
@@ -37,49 +39,36 @@ var s = ''; | ||
* Import Models from meta-data | ||
* @param {string} dialect | ||
* @param {string} connectString | ||
* @param {String} output | ||
* @param {Object} options | ||
*/ | ||
function exp(connectString, output, options) { | ||
function exp(dialect, connectString, options) { | ||
try { | ||
console.log('Exporting metadata from ' + chalk.yellow(connectString)); | ||
console.log('Exporting metadata..'); | ||
console.log(''); | ||
const startTime = (new Date).getTime(); | ||
const includeSchemas = options.schema ? options.schema.split(',') : undefined; | ||
const includeTables = options.include ? options.include.split(',') : undefined; | ||
const excludeTables = options.exclude ? options.exclude.split(',') : undefined; | ||
if (options.schema) | ||
console.log('Schama : ' + chalk.yellow(options.schema)); | ||
if (options.include) | ||
console.log('Included tables: ' + chalk.yellow(options.include)); | ||
if (options.exclude) | ||
console.log('Excluded tables: ' + chalk.yellow(options.exclude)); | ||
console.log(''); | ||
// Build configuration | ||
const cfg = {}; | ||
const m = connectString.match(/^(\w+)(?::?(\w+):?(\w+)?)?@(.+)$/); | ||
assert(m, 'connect string "' + connectString + '" is not valid'); | ||
cfg.dialect = m[1]; | ||
cfg.user = m[2]; | ||
cfg.password = m[3]; | ||
cfg.connectString = m[4]; | ||
cfg.naming = options.naming; | ||
cfg.dialect = dialect; | ||
cfg.connectString = connectString; | ||
cfg.defaults = { | ||
naming: options.naming | ||
}; | ||
sqb.use(require('sqb-connect-' + cfg.dialect)); | ||
try { | ||
sqb.use(require('sqb-connect-' + dialect)); | ||
} catch (e) { | ||
console.log(chalk.red('No driver found for dialect "' + dialect + '"')); | ||
} | ||
const pool = sqb.pool(cfg); | ||
const exporter = new uniqorm.MetadataExporter(pool, { | ||
includeSchemas: includeSchemas, | ||
includeTables: includeTables, | ||
excludeTables: excludeTables | ||
const exporter = new uniqorm.MetadataExporter(); | ||
exporter.on('connecting', function() { | ||
console.log('Connecting to database..'); | ||
}); | ||
exporter.on('connected', function() { | ||
console.log('Connected'); | ||
}); | ||
if (process.env.DEBUG) | ||
pool.on('execute', function(q) { | ||
console.log(q.sql); | ||
}); | ||
//exporter.on('process', | ||
exporter.on('process', function(v, v2, v3) { | ||
@@ -105,16 +94,17 @@ switch (v) { | ||
} | ||
}); | ||
exporter.execute().then(function(result) { | ||
exporter.execute(pool, { | ||
filter: options.filter, | ||
naming: options.naming | ||
}).then(function(result) { | ||
const str = JSON.stringify(result, null, '\t'); | ||
const ms = ((new Date).getTime() - startTime); | ||
const sec = Math.round(ms / 10) / 10; | ||
if (output) { | ||
fs.writeFile(output, str, 'utf8', function(err) { | ||
if (options.write) { | ||
fs.writeFile(path.resolve(appdir, options.write), str, 'utf8', function(err) { | ||
if (err) | ||
logError('Write file failed', err); | ||
else { | ||
console.log('Output file created: ' + output); | ||
console.log('Output file created: ' + options.write); | ||
console.log(chalk.green('Completed in ' + sec + ' sec')); | ||
@@ -146,16 +136,15 @@ } | ||
.version(pkg.version) | ||
.command('extract <connectString> <output>') | ||
.command('extract <dialect> <connectString>') | ||
.description('Extracts meta-data from database\n\n' + | ||
chalk.black(' connectString:') + | ||
chalk.yellow(' A formatted string to connect database.\n') + | ||
chalk.yellow(' dialect[:user[:password]]@database'), | ||
chalk.black(' schema:') + | ||
chalk.yellow(' Name of the database schema'), | ||
chalk.black(' output:') + | ||
chalk.yellow(' Output filename') | ||
chalk.yellow(' A formatted string to connect database. Format is specific to the dialect.') + | ||
chalk.black(' output:') + chalk.yellow(' Output filename') | ||
) | ||
.option('-s, --schema <schema>', 'Comma seperated schema names to be included in export list. All schemas will be exported if not specified') | ||
.option('-i, --include <table>', 'Comma seperated table names to be included in export list. All tables will be exported if not specified') | ||
.option('-e, --exclude <table>', 'Comma seperated table names to be excluded from export list') | ||
.option('-n, --naming <rule>', 'Naming enumeration value. (lowercase,uppercase)') | ||
.option('-f, --filter <filter>', 'Filtering pattern\n' + | ||
'SCHEMA1.{TABLE1,MY_*} > extracts tables from SCHEMA1\n' + | ||
'SCHEMA2.* > extracts all tables from SCHEMA2\n' + | ||
'TBL_* > extracts all tables of starts with TBL* word\n' + | ||
'SCHEMA1.{TABLE1,MY_*}|SCHEMA2.*|TBL_* > combine filters' | ||
) | ||
.option('-n, --naming <value>', 'Naming rule for table and column names. (lowercase,uppercase)') | ||
.option('-w, --write <fileName>', 'Write result json to given file') | ||
@@ -162,0 +151,0 @@ .action(exp); |
@@ -15,6 +15,19 @@ /* UNIQORM | ||
/** | ||
* @param {String} name | ||
* @param {Object} def | ||
* @constructor | ||
*/ | ||
function Field() { | ||
this._fieldType = Field.DataType.DATA; | ||
function Field(name, def) { | ||
/** | ||
* @property | ||
* @type {string} | ||
*/ | ||
this.fieldType = Field.FieldType.DATA; | ||
this.name = name; | ||
this.fieldName = def.fieldName || name; | ||
if (def) { | ||
this.notNull = def.notNull; | ||
this.defaultValue = def.defaultValue; | ||
this.primaryKey = def.primaryKey; | ||
} | ||
} | ||
@@ -67,18 +80,2 @@ | ||
/** | ||
* @type {int} | ||
*/ | ||
get fieldType() { | ||
return this._fieldType; | ||
}, | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* @param {int} value | ||
*/ | ||
set fieldType(value) { | ||
this._fieldType = value; | ||
}, | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* @type {*} | ||
@@ -138,12 +135,12 @@ */ | ||
/** @export @enum {number} */ | ||
Field.DataType = {}; | ||
Field.FieldType = {}; | ||
/** @export */ | ||
Field.DataType.DATA = /** @type {!Field.DataType} */ (0); | ||
Field.FieldType.DATA = /** @type {!Field.FieldType} */ (0); | ||
/** @export */ | ||
Field.DataType.AGGREGATE = /** @type {!Field.DataType} */ (1); | ||
Field.FieldType.AGGREGATE = /** @type {!Field.FieldType} */ (1); | ||
/** @export */ | ||
Field.DataType.CALCULATED = /** @type {!Field.DataType} */ (2); | ||
Field.FieldType.CALCULATED = /** @type {!Field.FieldType} */ (2); | ||
@@ -150,0 +147,0 @@ /** |
@@ -13,3 +13,3 @@ /* UNIQORM | ||
*/ | ||
const INTEGER = require('./INTEGER'); | ||
const INTEGER = require('../fields/INTEGER'); | ||
@@ -23,24 +23,23 @@ /** | ||
* | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends INTEGER | ||
*/ | ||
function BIGINT() { | ||
INTEGER.call(this); | ||
function BIGINT(alias, def) { | ||
INTEGER.apply(this, arguments); | ||
} | ||
const proto = BIGINT.prototype = { | ||
get jsType() { | ||
return 'Number'; | ||
BIGINT.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'BIGINT'; | ||
} | ||
}; | ||
Object.setPrototypeOf(proto, INTEGER.prototype); | ||
proto.constructor = BIGINT; | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'BIGINT'; | ||
}; | ||
Object.setPrototypeOf(BIGINT.prototype, INTEGER.prototype); | ||
BIGINT.prototype.constructor = BIGINT; |
@@ -13,3 +13,3 @@ /* UNIQORM | ||
*/ | ||
const Field = require('../Field'); | ||
const BUFFER = require('./BUFFER'); | ||
@@ -23,25 +23,22 @@ /** | ||
* | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends Field | ||
*/ | ||
function BLOB() { | ||
Field.call(this); | ||
function BLOB(alias, def) { | ||
BUFFER.apply(this, arguments); | ||
} | ||
const proto = BLOB.prototype = { | ||
get jsType() { | ||
return 'Buffer'; | ||
BLOB.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'BLOB'; | ||
} | ||
}; | ||
Object.setPrototypeOf(proto, Field.prototype); | ||
proto.constructor = BLOB; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'BLOB'; | ||
}; | ||
Object.setPrototypeOf(BLOB.prototype, BUFFER.prototype); | ||
BLOB.prototype.constructor = BLOB; |
@@ -13,3 +13,3 @@ /* UNIQORM | ||
*/ | ||
const BLOB = require('./BLOB'); | ||
const Field = require('../Field'); | ||
@@ -23,24 +23,30 @@ /** | ||
* | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends BLOB | ||
*/ | ||
function BUFFER() { | ||
BLOB.call(this); | ||
function BUFFER(alias, def) { | ||
Field.apply(this, arguments); | ||
} | ||
const proto = BUFFER.prototype = { | ||
BUFFER.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
*/ | ||
get jsType() { | ||
return 'Buffer'; | ||
}, | ||
/** | ||
* | ||
* @return {string} | ||
*/ | ||
get sqlType() { | ||
return 'BUFFER'; | ||
} | ||
}; | ||
Object.setPrototypeOf(proto, BLOB.prototype); | ||
proto.constructor = BUFFER; | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'BUFFER'; | ||
}; | ||
Object.setPrototypeOf(BUFFER.prototype, Field.prototype); | ||
BUFFER.prototype.constructor = BUFFER; |
@@ -13,3 +13,3 @@ /* UNIQORM | ||
*/ | ||
const VARCHAR = require('./VARCHAR'); | ||
const Field = require('../Field'); | ||
@@ -23,22 +23,33 @@ /** | ||
* | ||
* @param {Number} length | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends VARCHAR | ||
*/ | ||
function CHAR(length) { | ||
VARCHAR.call(this, length); | ||
function CHAR(alias, def) { | ||
Field.apply(this, arguments); | ||
this._charLength = def.charLength; | ||
if (def.defaultValue) | ||
this._defaultValue = String(def.defaultValue); | ||
} | ||
const proto = CHAR.prototype = {}; | ||
Object.setPrototypeOf(proto, VARCHAR.prototype); | ||
proto.constructor = CHAR; | ||
CHAR.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
*/ | ||
get jsType() { | ||
return 'String'; | ||
}, | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'CHAR(' + (this._charLength) + ')'; | ||
} | ||
}; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'CHAR'; | ||
}; | ||
Object.setPrototypeOf(CHAR.prototype, Field.prototype); | ||
CHAR.prototype.constructor = CHAR; |
@@ -22,25 +22,30 @@ /* UNIQORM | ||
* | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends Field | ||
*/ | ||
function CLOB() { | ||
Field.call(this); | ||
function CLOB(alias, def) { | ||
Field.apply(this, arguments); | ||
} | ||
const proto = CLOB.prototype = { | ||
CLOB.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
*/ | ||
get jsType() { | ||
return 'String'; | ||
}, | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'CLOB(' + (this._charLength) + ')'; | ||
} | ||
}; | ||
Object.setPrototypeOf(proto, Field.prototype); | ||
proto.constructor = CLOB; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'CLOB'; | ||
}; | ||
Object.setPrototypeOf(CLOB.prototype, Field.prototype); | ||
CLOB.prototype.constructor = CLOB; |
@@ -22,34 +22,25 @@ /* UNIQORM | ||
* | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends TIMESTAMP | ||
*/ | ||
function DATE() { | ||
TIMESTAMP.call(this); | ||
function DATE(alias, def) { | ||
TIMESTAMP.apply(this, arguments); | ||
if (this._defaultValue) | ||
this._defaultValue.setHours(0, 0, 0, 0); | ||
} | ||
const proto = DATE.prototype = {}; | ||
Object.setPrototypeOf(proto, TIMESTAMP.prototype); | ||
proto.constructor = DATE; | ||
/** | ||
* @param {*} value | ||
* @return {TIMESTAMP} | ||
*/ | ||
proto.setDefaultValue = function(value) { | ||
if (value) { | ||
value = value instanceof Date ? value : new Date(value); | ||
value.setHours(0, 0, 0, 0); | ||
DATE.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'DATE'; | ||
} | ||
TIMESTAMP.prototype.setDefaultValue.call(this, value); | ||
return this; | ||
}; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'DATE'; | ||
}; | ||
Object.setPrototypeOf(DATE.prototype, TIMESTAMP.prototype); | ||
DATE.prototype.constructor = DATE; |
@@ -13,3 +13,3 @@ /* UNIQORM | ||
*/ | ||
const Field = require('../Field'); | ||
const DOUBLE = require('../fields/DOUBLE'); | ||
@@ -22,39 +22,23 @@ /** | ||
/** | ||
* | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends Field | ||
*/ | ||
function FLOAT() { | ||
Field.call(this); | ||
function FLOAT(alias, def) { | ||
DOUBLE.apply(this, arguments); | ||
} | ||
const proto = FLOAT.prototype = { | ||
get jsType() { | ||
return 'Number'; | ||
FLOAT.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'FLOAT'; | ||
} | ||
}; | ||
Object.setPrototypeOf(proto, Field.prototype); | ||
proto.constructor = FLOAT; | ||
//noinspection JSCheckFunctionSignatures | ||
/** | ||
* | ||
* @param {int} value | ||
* @return {INTEGER} | ||
* @override | ||
*/ | ||
proto.setDefaultValue = function(value) { | ||
Field.prototype.setDefaultValue.call(this, value !== undefined ? | ||
parseFloat(value) : undefined); | ||
return this; | ||
}; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'FLOAT'; | ||
}; | ||
Object.setPrototypeOf(FLOAT.prototype, DOUBLE.prototype); | ||
FLOAT.prototype.constructor = FLOAT; |
@@ -22,38 +22,32 @@ /* UNIQORM | ||
* | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends Field | ||
*/ | ||
function INTEGER() { | ||
Field.call(this); | ||
function INTEGER(alias, def) { | ||
Field.apply(this, arguments); | ||
if (def.defaultValue) | ||
this._defaultValue = parseInt(def.defaultValue, 10); | ||
} | ||
const proto = INTEGER.prototype = { | ||
INTEGER.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
*/ | ||
get jsType() { | ||
return 'Number'; | ||
}, | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'INTEGER'; | ||
} | ||
}; | ||
Object.setPrototypeOf(proto, Field.prototype); | ||
proto.constructor = INTEGER; | ||
//noinspection JSCheckFunctionSignatures | ||
/** | ||
* | ||
* @param {int} value | ||
* @return {INTEGER} | ||
* @override | ||
*/ | ||
proto.setDefaultValue = function(value) { | ||
Field.prototype.setDefaultValue.call(this, value !== undefined ? | ||
parseInt(value) : undefined); | ||
return this; | ||
}; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'INTEGER'; | ||
}; | ||
Object.setPrototypeOf(INTEGER.prototype, Field.prototype); | ||
INTEGER.prototype.constructor = INTEGER; |
@@ -13,3 +13,3 @@ /* UNIQORM | ||
*/ | ||
const Field = require('../Field'); | ||
const DOUBLE = require('../fields/DOUBLE'); | ||
@@ -23,94 +23,29 @@ /** | ||
* | ||
* @param {Number} precision | ||
* @param {Number} scale | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends Field | ||
*/ | ||
function NUMBER(precision, scale) { | ||
Field.call(this); | ||
if (!precision) | ||
this.setPrecision(precision); | ||
if (!scale) | ||
this.setPrecision(scale); | ||
function NUMBER(alias, def) { | ||
DOUBLE.apply(this, arguments); | ||
if (def && def.precision != null) | ||
this._precision = def.precision; | ||
if (def && def.scale != null) | ||
this._scale = def.scale; | ||
} | ||
const proto = NUMBER.prototype = { | ||
get jsType() { | ||
return 'Number'; | ||
}, | ||
DOUBLE.prototype = { | ||
/** | ||
* @type {int} | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get precision() { | ||
return this._precision; | ||
}, | ||
/** | ||
* @param {int} val | ||
*/ | ||
set precision(val) { | ||
this._precision = parseInt(val); | ||
}, | ||
/** | ||
* @type {int} | ||
*/ | ||
get scale() { | ||
return this._scale; | ||
}, | ||
/** | ||
* @param {int} val | ||
*/ | ||
set scale(val) { | ||
this._scale = parseInt(val) || 0; | ||
get SqlType() { | ||
return 'NUMBER' + (this._precision || this._scale ? | ||
'(' + (this._precision || 18) + ',' + | ||
(this._scale || 0) + ')' : ''); | ||
} | ||
}; | ||
Object.setPrototypeOf(proto, Field.prototype); | ||
proto.constructor = NUMBER; | ||
//noinspection JSCheckFunctionSignatures | ||
/** | ||
* | ||
* @param {Number} value | ||
* @return {NUMBER} | ||
* @override | ||
*/ | ||
proto.setDefaultValue = function(value) { | ||
Field.prototype.setDefaultValue.call(this, value !== undefined ? | ||
parseFloat(value) : undefined); | ||
return this; | ||
}; | ||
/** | ||
* | ||
* @param {int} [value = 18] | ||
* @return {NUMBER} | ||
*/ | ||
proto.setPrecision = function(value) { | ||
this.precision = value !== undefined ? value : 18; | ||
return this; | ||
}; | ||
/** | ||
* | ||
* @param {int} [value = 0] | ||
* @return {NUMBER} | ||
*/ | ||
proto.setScale = function(value) { | ||
this.scale = value !== undefined ? value : 0; | ||
return this; | ||
}; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'NUMBER' + (this._precision || this._scale ? | ||
'(' + (this._precision || 18) + ',' + (this._scale || 0) + | ||
')' : ''); | ||
}; | ||
Object.setPrototypeOf(NUMBER.prototype, DOUBLE.prototype); | ||
NUMBER.prototype.constructor = NUMBER; |
@@ -22,34 +22,25 @@ /* UNIQORM | ||
* | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends TIMESTAMP | ||
*/ | ||
function TIME() { | ||
TIMESTAMP.call(this); | ||
function TIME(alias, def) { | ||
TIMESTAMP.apply(this, arguments); | ||
if (this._defaultValue) | ||
this._defaultValue.setFullYear(0, 0, 0); | ||
} | ||
const proto = TIME.prototype = {}; | ||
Object.setPrototypeOf(proto, TIMESTAMP.prototype); | ||
proto.constructor = TIME; | ||
/** | ||
* @param {*} value | ||
* @return {TIME} | ||
*/ | ||
proto.setDefaultValue = function(value) { | ||
if (value) { | ||
value = value instanceof Date ? value : new Date(value); | ||
value.setFullYear(0, 0, 0); | ||
TIME.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'TIME'; | ||
} | ||
TIMESTAMP.prototype.setDefaultValue.call(this, value); | ||
return this; | ||
}; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'TIME'; | ||
}; | ||
Object.setPrototypeOf(TIME.prototype, TIMESTAMP.prototype); | ||
TIME.prototype.constructor = TIME; |
@@ -22,36 +22,33 @@ /* UNIQORM | ||
* | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends Field | ||
*/ | ||
function TIMESTAMP() { | ||
Field.call(this); | ||
function TIMESTAMP(alias, def) { | ||
Field.apply(this, arguments); | ||
if (def.defaultValue) | ||
this._defaultValue = def.defaultValue instanceof Date ? | ||
def.defaultValue : new Date(def.defaultValue); | ||
} | ||
const proto = TIMESTAMP.prototype = { | ||
TIMESTAMP.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
*/ | ||
get jsType() { | ||
return 'Date'; | ||
}, | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'TIMESTAMP'; | ||
} | ||
}; | ||
Object.setPrototypeOf(proto, Field.prototype); | ||
proto.constructor = TIMESTAMP; | ||
/** | ||
* @param {*} value | ||
* @return {TIMESTAMP} | ||
*/ | ||
proto.setDefaultValue = function(value) { | ||
Field.prototype.setDefaultValue.call(this, | ||
value !== undefined ? | ||
(value instanceof Date ? value : new Date(value)) : undefined); | ||
return this; | ||
}; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'TIMESTAMP'; | ||
}; | ||
Object.setPrototypeOf(TIMESTAMP.prototype, Field.prototype); | ||
TIMESTAMP.prototype.constructor = TIMESTAMP; |
@@ -13,3 +13,3 @@ /* UNIQORM | ||
*/ | ||
const Field = require('../Field'); | ||
const CHAR = require('./CHAR'); | ||
@@ -23,48 +23,30 @@ /** | ||
* | ||
* @param {Number} length | ||
* @param {String} alias | ||
* @param {Object} def | ||
* @constructor | ||
* @extends Field | ||
*/ | ||
function VARCHAR(length) { | ||
Field.call(this); | ||
if (length !== undefined) | ||
this.setLength(parseInt(length)); | ||
function VARCHAR(alias, def) { | ||
CHAR.apply(this, arguments); | ||
} | ||
const proto = VARCHAR.prototype = { | ||
VARCHAR.prototype = { | ||
/** | ||
* | ||
* @return {string} | ||
*/ | ||
get jsType() { | ||
return 'String'; | ||
}, | ||
/** | ||
* | ||
* @return {string} | ||
* @constructor | ||
*/ | ||
get SqlType() { | ||
return 'VARCHAR(' + (this._charLength) + ')'; | ||
} | ||
}; | ||
Object.setPrototypeOf(proto, Field.prototype); | ||
proto.constructor = VARCHAR; | ||
/** | ||
* @param {*} value | ||
* @return {VARCHAR} | ||
*/ | ||
proto.setDefaultValue = function(value) { | ||
Field.prototype.setDefaultValue.call(this, value !== undefined ? | ||
String(value) : undefined); | ||
return this; | ||
}; | ||
/** | ||
* | ||
* @param {int} [value = 1] | ||
* @return {VARCHAR} | ||
*/ | ||
proto.setLength = function(value) { | ||
this._length = value ? parseInt(value) : 1; | ||
return this; | ||
}; | ||
//noinspection JSUnusedGlobalSymbols | ||
/** | ||
* | ||
* @return {string} | ||
* @public | ||
*/ | ||
proto.toSql = function() { | ||
return 'VARCHAR' + (this._length ? '(' + this._length + ')' : ''); | ||
}; | ||
Object.setPrototypeOf(VARCHAR.prototype, CHAR.prototype); | ||
VARCHAR.prototype.constructor = VARCHAR; |
@@ -16,3 +16,3 @@ /* UNIQORM | ||
const Field = require('./Field'); | ||
const MetadataExporter = require('./MetadataExporter'); | ||
const MetadataExporter = require('./ModelExporter'); | ||
@@ -22,2 +22,3 @@ // Register field classes | ||
Field.register(require('./fields/BIGINT')); | ||
Field.register(require('./fields/SMALLINT')); | ||
Field.register(require('./fields/FLOAT')); | ||
@@ -38,4 +39,4 @@ Field.register(require('./fields/NUMBER')); | ||
Uniqorm.MetadataExporter = MetadataExporter; | ||
Uniqorm.DataType = Field.DataType; | ||
Uniqorm.FieldType = Field.FieldType; | ||
//Object.assign(module.exports, Field); |
151
lib/Model.js
@@ -14,8 +14,4 @@ /* UNIQORM | ||
const errorex = require('errorex'); | ||
const defineConst = require('putil-defineconst'); | ||
const ModelMeta = require('./ModelMeta'); | ||
const DeleteQuery = require('./queries/DeleteQuery'); | ||
const InsertQuery = require('./queries/InsertQuery'); | ||
const SelectQuery = require('./queries/SelectQuery'); | ||
const UpdateQuery = require('./queries/UpdateQuery'); | ||
const FindOne = require('./model/FindOne'); | ||
const FindAll = require('./model/FindAll'); | ||
//const RelationO2O = require('./relation-one2one'); | ||
@@ -28,3 +24,2 @@ | ||
const ArgumentError = errorex.ArgumentError; | ||
const MODEL_NAME_PATTERN = /^([A-Za-z]\w*)?(\.[A-Za-z]\w*)?$/; | ||
@@ -42,125 +37,40 @@ /** | ||
if (dbObj && | ||
!(typeof dbObj.select === 'function' && typeof dbObj.insert === 'function')) | ||
throw new ArgumentError('`dbObj` argument must be a SQB pool or connection instance'); | ||
!(typeof dbObj.select === 'function' && | ||
typeof dbObj.execute === 'function')) | ||
throw new ArgumentError('`dbObj` argument must be a SQB pool or Connection instance'); | ||
this._dbObj = dbObj || this.orm.pool; | ||
/* | ||
const aliases = []; | ||
aliases.push(this.tableAlias); | ||
for (const relation of this._relations) { | ||
const t = relation.foreignModel.meta.table; | ||
const aa = t.substring(t, 1).toLowerCase(); | ||
let a = aa; | ||
let i = 1; | ||
while (aliases.indexOf(a) >= 0) | ||
a = aa + (++i); | ||
aliases.push(a); | ||
//noinspection JSUndefinedPropertyAssignment | ||
relation.table = t; | ||
//noinspection JSUndefinedPropertyAssignment | ||
relation.tableAlias = a; | ||
}*/ | ||
} | ||
const proto = Model.prototype = {}; | ||
proto.constructor = Model; | ||
proto.delete = function() { | ||
const o = Object.create(DeleteQuery.prototype); | ||
DeleteQuery.call(o, this); | ||
return o; | ||
/** | ||
* Searches for one specific element in the database | ||
* | ||
* @param {...String} columns | ||
* @return {FindOne} | ||
*/ | ||
Model.prototype.findOne = function(columns) { | ||
return new FindOne(this, Array.prototype.slice.call(arguments)); | ||
}; | ||
proto.insert = function(values) { | ||
const o = Object.create(InsertQuery.prototype); | ||
InsertQuery.apply(o, Array.prototype.concat.apply([this], arguments)); | ||
return o; | ||
}; | ||
proto.select = function(colargs) { | ||
const o = Object.create(SelectQuery.prototype); | ||
SelectQuery.apply(o, Array.prototype.concat.apply([this], arguments)); | ||
return o; | ||
}; | ||
proto.update = function(values) { | ||
const o = Object.create(UpdateQuery.prototype); | ||
UpdateQuery.apply(o, Array.prototype.concat.apply([this], arguments)); | ||
return o; | ||
}; | ||
/** | ||
* Returns short info for field | ||
* Searches for multiple elements in the database | ||
* | ||
* @param {string} name - Field Name | ||
* @return {Object} | ||
* @param {...String} columns | ||
* @return {FindAll} | ||
*/ | ||
proto.getFieldInfo = function(name) { | ||
//noinspection JSUnresolvedVariable | ||
const f = this.meta.get(name); | ||
if (f) { | ||
//noinspection JSUnresolvedVariable | ||
return { | ||
owner: this, | ||
name: f.name, | ||
fieldName: f.fieldName, | ||
tableName: this.tableName, | ||
tableAlias: this.tableAlias, | ||
schemaName: this.schemaName | ||
}; | ||
} | ||
//noinspection JSUnresolvedVariable | ||
this._relations.forEach(function(relation) { | ||
if (relation.fields) { | ||
const f = relation.fields[name]; | ||
if (f) { | ||
return { | ||
owner: relation, | ||
name: name, | ||
fieldName: f, | ||
tableName: relation.tableName, | ||
tableAlias: relation.tableAlias, | ||
schemaName: relation.foreignSchema | ||
}; | ||
} | ||
} | ||
}); | ||
Model.prototype.findAll = function(columns) { | ||
return new FindAll(this, Array.prototype.slice.call(arguments)); | ||
}; | ||
Model.extend = function(name, modelDef) { | ||
if (!modelDef) { | ||
modelDef = name; | ||
name = null; | ||
} | ||
if (typeof modelDef !== 'object') | ||
throw new ArgumentError('`modelDef` argument is empty or is not valid'); | ||
name = name || modelDef.tableName; | ||
if (!(typeof name === 'string' && name.match(MODEL_NAME_PATTERN))) | ||
throw new ArgumentError('Invalid model name `%s`', name); | ||
const meta = new ModelMeta(modelDef); | ||
const _super = this; | ||
const ctor = function Model() { | ||
defineConst(this, { | ||
meta: meta | ||
}); | ||
_super.apply(this, arguments); | ||
}; | ||
ctor.prototype = Object.create(_super.prototype); | ||
ctor.prototype.constructor = ctor; | ||
name = name.replace(/\./, '') + 'Model'; | ||
defineConst(ctor, 'name', name.substring(0, 1).toUpperCase() + | ||
name.substring(1), false); | ||
defineConst(ctor, { | ||
meta: meta | ||
}); | ||
defineConst(ctor.prototype, { | ||
schemaName: meta.schemaName, | ||
tableName: meta.tableName, | ||
tableAlias: meta.tableName.substring(0, 1).toLowerCase(), | ||
relations: [] | ||
}); | ||
return ctor; | ||
Model.belongsTo = function(other, from, to) { | ||
/* | ||
if (!(other && typeof other.prototype.findOne === 'function')) | ||
throw new ArgumentError('Foreign model required as first argument'); | ||
const model = this.prototype; | ||
model.relations.push({ | ||
type: '1:1', | ||
foreignModel: other, | ||
from: from, | ||
to: to | ||
});*/ | ||
//console.log(this.prototype.tableName, other.prototype.tableName); | ||
}; | ||
@@ -193,1 +103,2 @@ | ||
@@ -15,2 +15,4 @@ /* UNIQORM | ||
const Model = require('./Model'); | ||
const defineConst = require('putil-defineconst'); | ||
const Field = require('./Field'); | ||
@@ -22,2 +24,3 @@ /** | ||
const ArgumentError = errorex.ArgumentError; | ||
const MODEL_NAME_PATTERN = /^(?:([A-Za-z]\w*)\.)?([A-Za-z]\w*)?$/; | ||
@@ -65,27 +68,137 @@ /** | ||
Uniqorm.prototype.define = function(name, modelDef) { | ||
if (!name) | ||
throw new ArgumentError('`name` argument required'); | ||
if (this.get(name)) | ||
throw new ArgumentError('Model `%s` already exists', name); | ||
const modelCTor = Model.extend(name, modelDef); | ||
modelCTor.prototype.orm = this; | ||
if (modelCTor.prototype.ownerName) | ||
name = modelCTor.prototype.ownerName + '.' + name; | ||
name = this.options.caseSensitive ? name : name.toLocaleLowerCase(); | ||
return this.models[name] = modelCTor; | ||
const modelCTor = extendModel(this, name, modelDef); | ||
var o = this.models; | ||
var v = modelCTor.prototype.schemaName; | ||
if (v) { | ||
o[v] = o[v] || {}; | ||
o = o[v]; | ||
} | ||
return o[modelCTor.prototype.tableName] = modelCTor; | ||
}; | ||
/** | ||
* Creates all Model classes from a single definition object | ||
* | ||
* @param {Object} modelDefs | ||
* @public | ||
*/ | ||
Uniqorm.prototype.defineAll = function(modelDefs) { | ||
const self = this; | ||
const modelKeys = Object.getOwnPropertyNames(modelDefs); | ||
/* Define models */ | ||
modelKeys.forEach(function(n) { | ||
self.define(n, modelDefs[n]); | ||
}); | ||
/* Define associations */ | ||
modelKeys.forEach(function(n) { | ||
const def = modelDefs[n]; | ||
if (def.foreignKeys && def.foreignKeys.length) { | ||
def.foreignKeys.forEach(function(o) { | ||
const fromModel = self.get(n); | ||
if (!fromModel) | ||
throw new ArgumentError('Unable to define foreign associations. Model (%s) not found', n); | ||
const toModel = self.get(o.model); | ||
if (!toModel) | ||
throw new ArgumentError('Unable to define foreign associations. Model (%s) not found', o.model); | ||
fromModel.belongsTo(toModel, o.from, o.to); | ||
}); | ||
} | ||
}); | ||
}; | ||
/** | ||
* Returns Model constructor | ||
* | ||
* @param {string} [name] | ||
* @param {string} [modelName] | ||
* @return {Function|undefined} | ||
* @public | ||
*/ | ||
Uniqorm.prototype.get = function(name) { | ||
if (!name) | ||
Uniqorm.prototype.get = function(modelName) { | ||
if (!modelName) | ||
return undefined; | ||
const n = this.options.caseSensitive ? name : name.toLocaleLowerCase(); | ||
return this.models[n]; | ||
const m = modelName.match(MODEL_NAME_PATTERN); | ||
if (!m) | ||
throw new ArgumentError('Invalid model modelName `%s`', modelName); | ||
var o = this.models; | ||
if (m[1]) | ||
o = o[m[1]]; | ||
return o && o[m[2]]; | ||
}; | ||
function extendModel(orm, modelName, modelDef) { | ||
if (!modelName) | ||
throw new ArgumentError('`modelName` argument required'); | ||
if (typeof modelDef !== 'object') | ||
throw new ArgumentError('`modelDef` argument is empty or is not valid'); | ||
if (!(typeof modelName === 'string' && modelName.match(MODEL_NAME_PATTERN))) | ||
throw new ArgumentError('Invalid model name `%s`', modelName); | ||
const m = modelName.match(MODEL_NAME_PATTERN); | ||
const schemaName = modelDef.schemaName || m[1]; | ||
const tableName = modelDef.tableName || m[2]; | ||
var primaryKeys; | ||
if (modelDef.primaryKey && modelDef.primaryKey.columns) { | ||
const x = modelDef.primaryKey.columns; | ||
if (typeof x === 'string') | ||
primaryKeys = modelDef.primaryKey.columns.split(/\s*,\s*/); | ||
else if (Array.isArray(x)) primaryKeys = x; | ||
else throw new ArgumentError('Array of String type allowed for property "primaryKeys"'); | ||
} | ||
const fields = buildFields(modelDef.fields, primaryKeys); | ||
/* Create model class */ | ||
const className = camelCase(m[1]) + camelCase(m[2]) + 'Model'; | ||
const _super = Model; | ||
const ctor = function Model() { | ||
_super.apply(this, arguments); | ||
}; | ||
Object.assign(ctor, Model); | ||
ctor.prototype = Object.create(_super.prototype); | ||
ctor.prototype.constructor = ctor; | ||
defineConst(ctor, 'name', className, false); | ||
defineConst(ctor.prototype, { | ||
orm: orm, | ||
name: className, | ||
schemaName: schemaName, | ||
tableName: tableName, | ||
fields: fields, | ||
primaryKeys: primaryKeys, | ||
relations: [] | ||
}, true); | ||
return ctor; | ||
} | ||
/** | ||
* | ||
* @param {Object} def | ||
* @param {Array} [primaryKeys] | ||
* @return {Object} | ||
*/ | ||
function buildFields(def, primaryKeys) { | ||
if (!def) | ||
throw new ArgumentError('Definition does not have `fields` property'); | ||
const fields = {}; | ||
Object.getOwnPropertyNames(def).forEach(function(name) { | ||
const o = def[name]; | ||
if (primaryKeys && primaryKeys.indexOf(name)) | ||
o.primaryKey = true; | ||
const Ctor = Field.get(o.dataType); | ||
if (!Ctor) | ||
throw new ArgumentError('Unknown data type "' + o.dataType + '"'); | ||
const f = fields[name] = Object.create(Ctor.prototype); | ||
Ctor.call(f, name, o); | ||
}); | ||
return fields; | ||
} | ||
/** | ||
* | ||
* @param {String} s | ||
* @return {string} | ||
*/ | ||
function camelCase(s) { | ||
return s.substring(0, 1).toUpperCase() + s.substring(1); | ||
} |
{ | ||
"name": "uniqorm", | ||
"description": "Easy to use, multi-dialect ORM framework for JavaScript", | ||
"version": "1.0.0-alpha.1", | ||
"version": "1.0.0-alpha.2", | ||
"author": "Panates Ltd.", | ||
@@ -24,17 +24,18 @@ "contributors": [ | ||
"chalk": "^2.3.0", | ||
"commander": "^2.11.0", | ||
"commander": "^2.13.0", | ||
"errorex": "^1.0.6", | ||
"putil-defineconst": "^1.0.0", | ||
"putil-defineconst": "^1.1.0", | ||
"putil-promisify": "^1.1.0", | ||
"putil-waterfall": "^1.1.2", | ||
"sqb": "^1.0.0-beta.4" | ||
"putil-waterfall": "^1.1.2" | ||
}, | ||
"devDependencies": { | ||
"babel-eslint": "^8.0.2", | ||
"eslint": "^4.11.0", | ||
"babel-eslint": "^8.2.1", | ||
"eslint": "^4.16.0", | ||
"eslint-config-google": "^0.9.1", | ||
"istanbul": "^0.4.5", | ||
"mocha": "^4.0.1" | ||
"mocha": "^4.1.0" | ||
}, | ||
"peerDependencies": {}, | ||
"peerDependencies": { | ||
"sqb": "^1.0.1-alpha.6" | ||
}, | ||
"engines": { | ||
@@ -41,0 +42,0 @@ "node": ">= 4.0" |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
4
45650
28
1691
- Removedsqb@^1.0.0-beta.4
Updatedcommander@^2.13.0
Updatedputil-defineconst@^1.1.0