Comparing version 1.0.0-alpha.8 to 1.0.0-alpha.9
111
lib/Model.js
@@ -14,5 +14,6 @@ /* UNIQORM | ||
const errorex = require('errorex'); | ||
const FindOne = require('./model/FindOne'); | ||
const FindAll = require('./model/FindAll'); | ||
//const RelationO2O = require('./relation-one2one'); | ||
const sqb = require('sqb'); | ||
const defineConst = require('putil-defineconst'); | ||
const Field = require('./Field'); | ||
const modelFind = require('./model/find'); | ||
@@ -24,2 +25,3 @@ /** | ||
const ArgumentError = errorex.ArgumentError; | ||
const MODEL_NAME_PATTERN = /^(?:([A-Za-z]\w*)\.)?([A-Za-z]\w*)?$/; | ||
@@ -32,22 +34,52 @@ /** | ||
/** | ||
* @param {Object} dbObj | ||
* @param {Uniqorm} owner | ||
* @param {String} name | ||
* @param {Object} def | ||
* @param {Object} def.fields | ||
* @constructor | ||
*/ | ||
function Model(dbObj) { | ||
if (dbObj && | ||
!(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; | ||
function Model(owner, name, def) { | ||
if (!name) | ||
throw new ArgumentError('`name` argument required'); | ||
if (!(typeof name === 'string' && name.match(MODEL_NAME_PATTERN))) | ||
throw new ArgumentError('Invalid model name `%s`', name); | ||
if (typeof def !== 'object') | ||
throw new ArgumentError('`def` argument is empty or is not valid'); | ||
if (typeof def.tableName !== 'string') | ||
throw new ArgumentError('`def.tableName` argument is empty or is not valid'); | ||
if (typeof def.fields !== 'object') | ||
throw new ArgumentError('`def.fields` argument is empty or is not valid'); | ||
var primaryKeys; | ||
const x = def.primaryKey.columns; | ||
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); | ||
defineConst(this, { | ||
name: name, | ||
owner: owner, | ||
schemaName: def.schemaName || undefined, | ||
tableName: def.tableName, | ||
fields: fields, | ||
primaryKeys: primaryKeys | ||
}); | ||
} | ||
Model.prototype.Op = sqb.Op; | ||
/** | ||
* Searches for one specific element in the database | ||
* | ||
* @param {...String} columns | ||
* @return {FindOne} | ||
* @param {Object} [dbobj] SQB pool or SQB connection | ||
* @param {Object} [options] | ||
* @param {Function} [callback] | ||
* @return {Promise|Undefined} | ||
*/ | ||
Model.prototype.findOne = function(columns) { | ||
return new FindOne(this, Array.prototype.slice.call(arguments)); | ||
}; | ||
Model.prototype.findOne = modelFind.findOne; | ||
@@ -57,9 +89,25 @@ /** | ||
* | ||
* @param {...String} columns | ||
* @return {FindAll} | ||
* @param {Object} [dbobj] SQB pool or SQB connection | ||
* @param {Object} [options] | ||
* @param {Function} [callback] | ||
* @return {Promise|Undefined} | ||
*/ | ||
Model.prototype.findAll = function(columns) { | ||
return new FindAll(this, Array.prototype.slice.call(arguments)); | ||
}; | ||
Model.prototype.findAll = modelFind.findAll; | ||
/** | ||
* Creates a Cursor that searches for multiple elements in the database | ||
* | ||
* @param {Object} [dbobj] SQB pool or SQB connection | ||
* @param {Object} [options] | ||
* @param {Function} [callback] | ||
* @return {Promise|Undefined} | ||
*/ | ||
Model.prototype.findCursor = modelFind.findCursor; | ||
/* | ||
* | ||
* @param other | ||
* @param from | ||
* @param to | ||
*/ | ||
Model.belongsTo = function(other, from, to) { | ||
@@ -104,2 +152,23 @@ /* | ||
/** | ||
* | ||
* @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; | ||
} |
@@ -15,4 +15,2 @@ /* UNIQORM | ||
const Model = require('./Model'); | ||
const defineConst = require('putil-defineconst'); | ||
const Field = require('./Field'); | ||
@@ -59,4 +57,3 @@ /** | ||
/** | ||
* Creates a new Model class and adds to list | ||
* If argument is a configuration object it extends a new Model class | ||
* Creates a new Model | ||
* | ||
@@ -69,42 +66,8 @@ * @param {String} name | ||
Uniqorm.prototype.define = function(name, modelDef) { | ||
if (typeof name !== 'string') | ||
throw new ArgumentError('A string value required for model name'); | ||
if (this.get(name)) | ||
throw new ArgumentError('Model `%s` already exists', name); | ||
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); | ||
}); | ||
} | ||
}); | ||
return this.models[name] = new Model(this, name, modelDef); | ||
}; | ||
@@ -130,78 +93,1 @@ | ||
}; | ||
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].replace(/_/g, '')) + | ||
camelCase(m[2].replace(/_/g, '')) + '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.8", | ||
"version": "1.0.0-alpha.9", | ||
"author": "Panates Ltd.", | ||
@@ -12,11 +12,12 @@ "contributors": [ | ||
"main": "lib/index.js", | ||
"bin": "./bin/cli.js", | ||
"keywords": [ | ||
"javascript", | ||
"framework", | ||
"orm", | ||
"sql", | ||
"data-mapping", | ||
"database", | ||
"oracle", | ||
"framework" | ||
"postgres", | ||
"pg", | ||
"sqlite" | ||
], | ||
@@ -33,9 +34,9 @@ "dependencies": { | ||
"babel-eslint": "^8.2.1", | ||
"eslint": "^4.16.0", | ||
"eslint": "^4.17.0", | ||
"eslint-config-google": "^0.9.1", | ||
"istanbul": "^0.4.5", | ||
"mocha": "^4.1.0" | ||
"mocha": "^5.0.0" | ||
}, | ||
"peerDependencies": { | ||
"sqb": "^1.0.1-alpha.6" | ||
"sqb": "^1.0.1-rc.1" | ||
}, | ||
@@ -42,0 +43,0 @@ "engines": { |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
1
41584
26
1542