Comparing version 1.0.0-alpha.13 to 1.0.0-alpha.14
224
lib/Model.js
@@ -18,2 +18,3 @@ /* UNIQORM | ||
const promisify = require('putil-promisify'); | ||
const ModelError = require('./ModelError'); | ||
@@ -24,2 +25,3 @@ /** | ||
*/ | ||
const Op = sqb.Op; | ||
const ArgumentError = errorex.ArgumentError; | ||
@@ -42,23 +44,31 @@ const MODEL_NAME_PATTERN = /^(?:([A-Za-z]\w*)\.)?([A-Za-z]\w*)?$/; | ||
if (!name) | ||
throw new ArgumentError('`name` argument required'); | ||
throw new ArgumentError('Model name required'); | ||
if (!(typeof name === 'string' && name.match(MODEL_NAME_PATTERN))) | ||
throw new ArgumentError('Invalid model name `%s`', name); | ||
throw new ArgumentError('Invalid model name "%s"', name); | ||
if (typeof def !== 'object') | ||
throw new ArgumentError('`def` argument is empty or is not valid'); | ||
throw new ArgumentError('Model definition argument (def) is empty or is not valid'); | ||
if (typeof def.tableName !== 'string') | ||
throw new ArgumentError('`def.tableName` argument is empty or is not valid'); | ||
throw new ArgumentError('"tableName" property is empty or is not valid'); | ||
if (typeof def.fields !== 'object') | ||
throw new ArgumentError('`def.fields` argument is empty or is not valid'); | ||
throw new ArgumentError('`fields` argument is empty or is not valid'); | ||
var primaryKeys; | ||
const x = def.primaryKeys; | ||
if (x) { | ||
primaryKeys = typeof x === 'string' ? x.split(/\s*,\s*/) : x; | ||
if (!Array.isArray(x)) | ||
throw new ArgumentError('Array of String type allowed for property "primaryKeys"'); | ||
} | ||
const fields = buildFields(def.fields, primaryKeys); | ||
/* Build field list */ | ||
const fields = {}; | ||
const keyFields = []; | ||
Object.getOwnPropertyNames(def.fields).forEach(function(name) { | ||
const o = def.fields[name]; | ||
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); | ||
if (o.primaryKey) { | ||
f.primaryKey = true; | ||
keyFields.push(name); | ||
} | ||
}); | ||
defineConst(this, { | ||
@@ -70,3 +80,3 @@ name: name, | ||
fields: fields, | ||
primaryKeys: primaryKeys | ||
keyFields: keyFields | ||
}); | ||
@@ -131,6 +141,7 @@ } | ||
}); | ||
options = prepareFindOptions(self, options || {}); | ||
/* Prepare query */ | ||
const query = prepareFindQuery(self, options || {}); | ||
options.cursor = false; | ||
options.rowset = false; | ||
const query = prepareFindQuery(self, options); | ||
/* Execute query */ | ||
query.execute(options, function(err, result) { | ||
@@ -160,6 +171,7 @@ if (!err && result && result.rows.length) | ||
}); | ||
options = prepareFindOptions(self, options || {}); | ||
/* Prepare query */ | ||
const query = prepareFindQuery(self, options || {}); | ||
options.cursor = true; | ||
options.rowset = false; | ||
const query = prepareFindQuery(self, options); | ||
/* Execute query */ | ||
query.execute(options, function(err, result) { | ||
@@ -173,3 +185,3 @@ if (!err && result && result.cursor) | ||
/** | ||
* Creates a Cursor that searches for multiple elements in the database | ||
* Inserts a new record | ||
* | ||
@@ -193,2 +205,3 @@ * @param {Object} [attributes] | ||
}); | ||
options = options || {}; | ||
@@ -198,7 +211,10 @@ options.objectRows = true; | ||
self.owner.options.validateFields; | ||
if (options.returning && options.returning !== '*') | ||
options.returning = Array.isArray(options.returning) ? options.returning : | ||
[options.returning]; | ||
const query = prepareCreateQuery(self, attributes, options); | ||
/* Prepare query */ | ||
const dbobj = (options.connection || this.owner.pool); | ||
const values = prepareValues(this, attributes, options); | ||
const query = dbobj | ||
.insert(self.tableNameFull, values) | ||
.returning(prepareReturning(self, options)); | ||
/* Execute query */ | ||
query.execute(options, function(err, result) { | ||
@@ -211,2 +227,43 @@ if (!err) | ||
/** | ||
* Updates the record | ||
* | ||
* @param {Object} [attributes] | ||
* @param {Object} [options] | ||
* @param {Function} [callback] | ||
* @return {Promise|Undefined} | ||
*/ | ||
Model.prototype.update = function(attributes, options, callback) { | ||
if (typeof attributes !== 'object') | ||
throw new ArgumentError('Attributes required to update model instance'); | ||
if (typeof options === 'function') { | ||
callback = options; | ||
options = null; | ||
} | ||
const self = this; | ||
if (!callback) | ||
return promisify.fromCallback(function(cb) { | ||
self.update(attributes, options, cb); | ||
}); | ||
options = options || {}; | ||
options.objectRows = true; | ||
options.validateFields = options.validateFields || | ||
self.owner.options.validateFields; | ||
/* Prepare query */ | ||
const dbobj = (options.connection || this.owner.pool); | ||
const values = prepareValues(this, attributes, options); | ||
const query = dbobj | ||
.update(this.tableNameFull, values) | ||
.where(prepareWhere(this, attributes)) | ||
.returning(prepareReturning(this, options)); | ||
/* Execute query */ | ||
query.execute(options, function(err, result) { | ||
if (!err) | ||
return callback(null, (result.rows && result.rows[0]) || true); | ||
callback(err); | ||
}); | ||
}; | ||
/* | ||
@@ -257,25 +314,2 @@ * | ||
/** | ||
* | ||
* @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; | ||
} | ||
function buildSelectColumns(model, cols, options) { | ||
@@ -286,5 +320,5 @@ const result = {}; | ||
if (!m) { | ||
if (!options.validateFields) | ||
return; | ||
throw new ArgumentError('Invalid column definition(%s)', k); | ||
if (options.validateFields) | ||
throw new ArgumentError('"%s" is not a valid column name', k); | ||
return; | ||
} | ||
@@ -299,33 +333,3 @@ const name = m[1]; | ||
function prepareCreateQuery(model, attributes, options) { | ||
const dbobj = options.transaction || model.owner.pool; | ||
/* */ | ||
const values = {}; | ||
Object.getOwnPropertyNames(attributes).forEach(function(name) { | ||
const field = options.validateFields ? model.getField(name) : model.fields[name]; | ||
if (field) | ||
values[name] = attributes[name]; | ||
}); | ||
/* Prepare returning column list */ | ||
var a = (options.returning === '*') ? | ||
Object.getOwnPropertyNames(model.fields) : | ||
(options.returning && | ||
options.returning.length) ? options.returning : model.primaryKeys; | ||
a = buildSelectColumns(model, a, options); | ||
const query = dbobj | ||
.insert(model.tableNameFull, values); | ||
const returningColumns = {}; | ||
Object.getOwnPropertyNames(a).forEach(function(name) { | ||
const col = a[name]; | ||
const field = options.validateFields ? model.getField(name) : model.fields[name]; | ||
if (field) | ||
returningColumns[col] = field.jsType.toLowerCase(); | ||
}); | ||
query.returning(returningColumns); | ||
return query; | ||
} | ||
function prepareFindOptions(model, options) { | ||
function prepareFindQuery(model, options) { | ||
options.limit = (parseInt(options.limit) || 0) || 100; | ||
@@ -336,14 +340,11 @@ options.objectRows = options.objectRows || options.objectRows == null; | ||
if (options.fields) | ||
options.fields = Array.isArray(options.fields) ? options.fields : | ||
[options.fields]; | ||
options.fields = Array.isArray(options.fields) ? | ||
options.fields : [options.fields]; | ||
if (options.where) | ||
options.where = Array.isArray(options.where) ? options.where : | ||
[options.where]; | ||
options.where = Array.isArray(options.where) ? | ||
options.where : [options.where]; | ||
if (options.orderBy) | ||
options.orderBy = Array.isArray(options.orderBy) ? options.orderBy : | ||
[options.orderBy]; | ||
return options; | ||
} | ||
options.orderBy = Array.isArray(options.orderBy) ? | ||
options.orderBy : [options.orderBy]; | ||
function prepareFindQuery(model, options) { | ||
const dbobj = options.transaction || model.owner.pool; | ||
@@ -401,1 +402,46 @@ var orderColumns; | ||
} | ||
function prepareValues(model, attributes, options) { | ||
const values = {}; | ||
Object.getOwnPropertyNames(attributes).forEach(function(name) { | ||
const field = options.validateFields ? model.getField(name) : model.fields[name]; | ||
if (field && !field.primaryKey) | ||
values[name] = attributes[name]; | ||
}); | ||
return values; | ||
} | ||
function prepareWhere(model, attributes) { | ||
if (!(model.keyFields && model.keyFields.length)) | ||
throw new ModelError('No primary key defined for model "%s"', model.name); | ||
const where = []; | ||
var v; | ||
model.keyFields.forEach(function(key) { | ||
v = attributes[key]; | ||
if (v == null) | ||
throw new ArgumentError('Value required for key field "%s', key); | ||
where.push(Op.eq(key, v)); | ||
}); | ||
return Op.and.apply(null, where); | ||
} | ||
function prepareReturning(model, options) { | ||
var a; | ||
if ((options.returning === '*')) | ||
a = Object.getOwnPropertyNames(model.fields); | ||
else if (options.returning) { | ||
a = Array.isArray(options.returning) ? options.returning : | ||
[options.returning]; | ||
} else a = model.keyFields; | ||
a = buildSelectColumns(model, a, options); | ||
const returningColumns = {}; | ||
Object.getOwnPropertyNames(a).forEach(function(alias) { | ||
const fname = a[alias]; | ||
const field = options.validateFields ? model.getField(fname) : model.fields[fname]; | ||
if (field) | ||
returningColumns[fname] = field.jsType.toLowerCase(); | ||
}); | ||
return returningColumns; | ||
} |
@@ -179,5 +179,9 @@ /* UNIQORM | ||
return next(err); | ||
var a; | ||
ret.rows.forEach(function(col) { | ||
const tbl = getTbl(col.schema_name, col.table_name); | ||
tbl.primaryKeys = col.column_names.split(/\s*,\s*/); | ||
a = col.column_names.split(/\s*,\s*/); | ||
a.forEach(function(f) { | ||
tbl.fields[f].primaryKey = true; | ||
}); | ||
}); | ||
@@ -184,0 +188,0 @@ offset += ret.rows.length; |
{ | ||
"name": "uniqorm", | ||
"description": "Easy to use, multi-dialect ORM framework for JavaScript", | ||
"version": "1.0.0-alpha.13", | ||
"version": "1.0.0-alpha.14", | ||
"author": "Panates Ltd.", | ||
@@ -25,3 +25,3 @@ "contributors": [ | ||
"chalk": "^2.3.0", | ||
"commander": "^2.13.0", | ||
"commander": "^2.14.1", | ||
"errorex": "^1.0.6", | ||
@@ -40,3 +40,3 @@ "putil-defineconst": "^1.1.0", | ||
"peerDependencies": { | ||
"sqb": "^1.0.1-rc.2" | ||
"sqb": "^1.0.1-rc.3" | ||
}, | ||
@@ -43,0 +43,0 @@ "engines": { |
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
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
43895
26
1622
Updatedcommander@^2.14.1