1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594 |
- var Utils = require("./utils")
- , DAO = require("./dao")
- , DataTypes = require("./data-types")
- , Util = require('util')
- , sql = require('sql')
- , SqlString = require('./sql-string')
- , Transaction = require('./transaction')
- , QueryTypes = require('./query-types')
- module.exports = (function() {
- var DAOFactory = function(name, attributes, options) {
- this.options = Utils._.extend({
- timestamps: true,
- createdAt: 'createdAt',
- updatedAt: 'updatedAt',
- deletedAt: 'deletedAt',
- instanceMethods: {},
- classMethods: {},
- validate: {},
- freezeTableName: false,
- underscored: false,
- syncOnAssociation: true,
- paranoid: false,
- whereCollection: null,
- schema: null,
- schemaDelimiter: '',
- language: 'en',
- defaultScope: null,
- scopes: null,
- hooks: {
- beforeCreate: [],
- afterCreate: []
- }
- }, options || {})
- // error check options
- Utils._.each(options.validate, function(validator, validatorType) {
- if (Utils._.contains(Utils._.keys(attributes), validatorType)) {
- throw new Error("A model validator function must not have the same name as a field. Model: " + name + ", field/validation name: " + validatorType)
- }
- if (!Utils._.isFunction(validator)) {
- throw new Error("Members of the validate option must be functions. Model: " + name + ", error with validate member " + validatorType)
- }
- })
- this.name = name
- if (!this.options.tableName) {
- this.tableName = this.options.freezeTableName ? name : Utils.pluralize(name, this.options.language)
- } else {
- this.tableName = this.options.tableName
- }
- attributes = replaceReferencesWithTableNames(attributes)
- this.options.hooks = this.replaceHookAliases(this.options.hooks)
- this.rawAttributes = attributes
- this.daoFactoryManager = null // defined in init function
- this.associations = {}
- this.scopeObj = {}
- }
- Object.defineProperty(DAOFactory.prototype, 'attributes', {
- get: function() {
- return this.QueryGenerator.attributesToSQL(this.rawAttributes)
- }
- })
- Object.defineProperty(DAOFactory.prototype, 'sequelize', {
- get: function() { return this.daoFactoryManager.sequelize }
- })
- Object.defineProperty(DAOFactory.prototype, 'QueryInterface', {
- get: function() { return this.daoFactoryManager.sequelize.getQueryInterface() }
- })
- Object.defineProperty(DAOFactory.prototype, 'QueryGenerator', {
- get: function() { return this.QueryInterface.QueryGenerator }
- })
- // inject the node-sql methods to the dao factory in order to
- // receive the syntax sugar ...
- ;(function() {
- var instance = sql.define({ name: "dummy", columns: [] })
- for (var methodName in instance) {
- ;(function(methodName) {
- DAOFactory.prototype[methodName] = function() {
- var dataset = this.dataset()
- , result = dataset[methodName].apply(dataset, arguments)
- , dialect = this.daoFactoryManager.sequelize.options.dialect
- , self = this
- result.toSql = function() {
- var query = result.toQuery()
- return SqlString.format(query.text.replace(/(\$\d)/g, '?'), query.values, null, dialect) + ';'
- }
- result.exec = function(options) {
- options = Utils._.extend({
- transaction: null,
- type: QueryTypes.SELECT
- }, options || {})
- return self.QueryInterface.queryAndEmit([result.toSql(), self, options], 'snafu')
- }
- return result
- }
- })(methodName)
- }
- })()
- DAOFactory.prototype.init = function(daoFactoryManager) {
- var self = this
- this.daoFactoryManager = daoFactoryManager
- this.primaryKeys = {}
- self.options.uniqueKeys = {}
- Utils._.each(this.rawAttributes, function(columnValues, columnName) {
- if (columnValues.hasOwnProperty('unique') && columnValues.unique !== true && columnValues.unique !== false) {
- var idxName = columnValues.unique
- if (typeof columnValues.unique === "object") {
- idxName = columnValues.unique.name
- }
- self.options.uniqueKeys[idxName] = self.options.uniqueKeys[idxName] || {fields: [], msg: null}
- self.options.uniqueKeys[idxName].fields.push(columnName)
- self.options.uniqueKeys[idxName].msg = self.options.uniqueKeys[idxName].msg || columnValues.unique.msg || null
- }
- })
- Utils._.each(this.attributes, function(dataTypeString, attributeName) {
- if (dataTypeString.indexOf('PRIMARY KEY') !== -1) {
- self.primaryKeys[attributeName] = dataTypeString
- }
- })
- this.primaryKeyAttributes = Object.keys(this.primaryKeys)
- this.primaryKeyCount = this.primaryKeyAttributes.length
- this.options.hasPrimaryKeys = this.hasPrimaryKeys = this.primaryKeyCount > 0
- if (typeof this.options.defaultScope === "object") {
- Utils.injectScope.call(this, this.options.defaultScope)
- }
- // DAO prototype
- // WTF ... ?
- this.DAO = function() {
- DAO.apply(this, arguments);
- }
- Util.inherits(this.DAO, DAO);
-
- this._timestampAttributes = {}
- if (this.options.timestamps) {
- if (this.options.createdAt) {
- this._timestampAttributes.createdAt = Utils._.underscoredIf(this.options.createdAt, this.options.underscored)
- }
- if (this.options.updatedAt) {
- this._timestampAttributes.updatedAt = Utils._.underscoredIf(this.options.updatedAt, this.options.underscored)
- }
- if (this.options.paranoid && this.options.deletedAt) {
- this._timestampAttributes.deletedAt = Utils._.underscoredIf(this.options.deletedAt, this.options.underscored)
- }
- this.DAO.prototype._readOnlyAttributes = Object.keys(this._timestampAttributes)
- }
- this.DAO.prototype._hasReadOnlyAttributes = this.DAO.prototype._readOnlyAttributes && this.DAO.prototype._readOnlyAttributes.length
- this.DAO.prototype._isReadOnlyAttribute = Utils._.memoize(function (key) {
- return self.DAO.prototype._hasReadOnlyAttributes && self.DAO.prototype._readOnlyAttributes.indexOf(key) !== -1
- })
- addDefaultAttributes.call(this)
- addOptionalClassMethods.call(this)
- findAutoIncrementField.call(this)
- this.DAO.prototype.rawAttributes = this.rawAttributes;
- this.DAO.prototype._hasPrimaryKeys = this.options.hasPrimaryKeys
- this.DAO.prototype._isPrimaryKey = Utils._.memoize(function (key) {
- return self.primaryKeyAttributes.indexOf(key) !== -1 && key !== 'id'
- })
- if (this.options.instanceMethods) {
- Utils._.each(this.options.instanceMethods, function(fct, name) {
- self.DAO.prototype[name] = fct
- })
- }
- this.refreshAttributes();
- this.DAO.prototype.booleanValues = []
- this.DAO.prototype.dateAttributes = []
- this.DAO.prototype.defaultValues = {}
- this.DAO.prototype.validators = {}
- Utils._.each(this.rawAttributes, function (definition, name) {
- if (((definition === DataTypes.BOOLEAN) || (definition.type === DataTypes.BOOLEAN))) {
- self.DAO.prototype.booleanValues.push(name);
- }
- if (((definition === DataTypes.DATE) || (definition.type === DataTypes.DATE) || (definition.originalType === DataTypes.DATE))) {
- self.DAO.prototype.dateAttributes.push(name);
- }
- if (definition.hasOwnProperty('defaultValue')) {
- self.DAO.prototype.defaultValues[name] = Utils._.partial(
- Utils.toDefaultValue, definition.defaultValue)
- }
- if (definition.hasOwnProperty('validate')) {
- self.DAO.prototype.validators[name] = definition.validate;
- }
- })
- this.DAO.prototype._hasBooleanAttributes = !!this.DAO.prototype.booleanValues.length
- this.DAO.prototype._isBooleanAttribute = Utils._.memoize(function (key) {
- return self.DAO.prototype.booleanValues.indexOf(key) !== -1
- })
- this.DAO.prototype._hasDateAttributes = !!this.DAO.prototype.dateAttributes.length
- this.DAO.prototype._isDateAttribute = Utils._.memoize(function (key) {
- return self.DAO.prototype.dateAttributes.indexOf(key) !== -1
- })
- this.DAO.prototype.__factory = this
- this.DAO.prototype.daoFactory = this
- this.DAO.prototype.Model = this
- this.DAO.prototype.hasDefaultValues = !Utils._.isEmpty(this.DAO.prototype.defaultValues)
- this.DAO.prototype.daoFactoryName = this.name
- return this
- }
- DAOFactory.prototype.refreshAttributes = function() {
- var self = this
- , attributeManipulation = {};
- this.DAO.prototype._customGetters = {}
- this.DAO.prototype._customSetters = {}
- Utils._.each(['get', 'set'], function(type) {
- var opt = type + 'terMethods'
- , funcs = Utils._.clone(Utils._.isObject(self.options[opt]) ? self.options[opt] : {})
- , _custom = type === 'get' ? self.DAO.prototype._customGetters : self.DAO.prototype._customSetters
- Utils._.each(funcs, function (method, attribute) {
- _custom[attribute] = method
- if (type === 'get') {
- funcs[attribute] = function() {
- return this.get(attribute)
- }
- }
- if (type === 'set') {
- funcs[attribute] = function(value) {
- return this.set(attribute, value)
- }
- }
- })
- Utils._.each(self.rawAttributes, function(options, attribute) {
- if (options.hasOwnProperty(type)) {
- _custom[attribute] = options[type]
- }
- if (type === 'get') {
- funcs[attribute] = function() {
- return this.get(attribute)
- }
- }
- if (type === 'set') {
- funcs[attribute] = function(value) {
- return this.set(attribute, value)
- }
- }
- })
- Utils._.each(funcs, function(fct, name) {
- if (!attributeManipulation[name]) {
- attributeManipulation[name] = {
- configurable: true
- }
- }
- attributeManipulation[name][type] = fct
- })
- })
- this.DAO.prototype._hasCustomGetters = Object.keys(this.DAO.prototype._customGetters).length
- this.DAO.prototype._hasCustomSetters = Object.keys(this.DAO.prototype._customSetters).length
- Object.defineProperties(this.DAO.prototype, attributeManipulation)
- this.DAO.prototype.attributes = Object.keys(this.DAO.prototype.rawAttributes)
- this.DAO.prototype._isAttribute = Utils._.memoize(function (key) {
- return self.DAO.prototype.attributes.indexOf(key) !== -1
- })
- }
- DAOFactory.prototype.sync = function(options) {
- options = Utils._.extend({}, this.options, options || {})
- var self = this
- return new Utils.CustomEventEmitter(function(emitter) {
- var doQuery = function() {
- self
- .QueryInterface
- .createTable(self.getTableName(), self.attributes, options)
- .proxy(emitter, {events: ['error', 'sql']})
- .success(function() { emitter.emit('success', self) })
- }
- if (options.force) {
- self
- .drop(options)
- .proxy(emitter, {events: ['error', 'sql']})
- .success(doQuery)
- } else {
- doQuery()
- }
- }).run()
- }
- DAOFactory.prototype.drop = function(options) {
- // Only Postgres' QueryGenerator.dropTableQuery() will add schema manually
- var isPostgres = this.options.dialect === "postgres" || (!!this.daoFactoryManager && this.daoFactoryManager.sequelize.options.dialect === "postgres")
- , tableName = isPostgres ? this.tableName : this.getTableName()
- return this.QueryInterface.dropTable(tableName, options)
- }
- DAOFactory.prototype.dropSchema = function(schema) {
- return this.QueryInterface.dropSchema(schema)
- }
- DAOFactory.prototype.schema = function(schema, options) {
- this.options.schema = schema
- if (!!options) {
- if (typeof options === "string") {
- this.options.schemaDelimiter = options
- } else {
- if (!!options.schemaDelimiter) {
- this.options.schemaDelimiter = options.schemaDelimiter
- }
- }
- }
- return this
- }
- DAOFactory.prototype.getTableName = function() {
- return this.QueryGenerator.addSchema(this)
- }
- DAOFactory.prototype.scope = function(option) {
- var self = Object.create(this)
- , type
- , options
- , merge
- , i
- , scope
- , scopeName
- , scopeOptions
- , argLength = arguments.length
- , lastArg = arguments[argLength-1]
- // Set defaults
- scopeOptions = (typeof lastArg === "object" && !Array.isArray(lastArg) ? lastArg : {}) || {} // <-- for no arguments
- scopeOptions.silent = (scopeOptions !== null && scopeOptions.hasOwnProperty('silent') ? scopeOptions.silent : true)
- // Clear out any predefined scopes...
- self.scopeObj = {}
- // Possible formats for option:
- // String of arguments: 'hello', 'world', 'etc'
- // Array: ['hello', 'world', 'etc']
- // Object: {merge: 'hello'}, {method: ['scopeName' [, args1, args2..]]}, {merge: true, method: ...}
- if (argLength < 1 || !option) {
- return self
- }
- for (i = 0; i < argLength; i++) {
- options = Array.isArray(arguments[i]) ? arguments[i] : [arguments[i]]
- options.forEach(function(o){
- type = typeof o
- scope = null
- merge = false
- scopeName = null
- if (type === "object") {
- // Right now we only support a merge functionality for objects
- if (!!o.merge) {
- merge = true
- scopeName = o.merge[0]
- if (Array.isArray(o.merge) && !!self.options.scopes[scopeName]) {
- scope = self.options.scopes[scopeName].apply(self, o.merge.splice(1))
- }
- else if (typeof o.merge === "string") {
- scopeName = o.merge
- scope = self.options.scopes[scopeName]
- }
- }
- if (!!o.method) {
- if (Array.isArray(o.method) && !!self.options.scopes[o.method[0]]) {
- scopeName = o.method[0]
- scope = self.options.scopes[scopeName].apply(self, o.method.splice(1))
- merge = !!o.merge
- }
- else if (!!self.options.scopes[o.method]) {
- scopeName = o.method
- scope = self.options.scopes[scopeName].apply(self)
- }
- } else {
- scopeName = o
- scope = self.options.scopes[scopeName]
- }
- } else {
- scopeName = o
- scope = self.options.scopes[scopeName]
- }
- if (!!scope) {
- Utils.injectScope.call(self, scope, merge)
- }
- else if (scopeOptions.silent !== true && !!scopeName) {
- throw new Error("Invalid scope " + scopeName + " called.")
- }
- })
- }
- return self
- }
- // alias for findAll
- DAOFactory.prototype.all = function(options, queryOptions) {
- return this.findAll(options, queryOptions)
- }
- DAOFactory.prototype.findAll = function(options, queryOptions) {
- var hasJoin = false
- , tableNames = { }
- tableNames[this.tableName] = true
- options = optClone(options)
- if (typeof options === 'object') {
- if (options.hasOwnProperty('include') && options.include) {
- hasJoin = true
- validateIncludedElements.call(this, options, tableNames)
- }
- // whereCollection is used for non-primary key updates
- this.options.whereCollection = options.where || null
- }
- options = paranoidClause.call(this, options)
- return this.QueryInterface.select(this, this.getTableName(), options, Utils._.defaults({
- type: QueryTypes.SELECT,
- hasJoin: hasJoin,
- tableNames: Object.keys(tableNames)
- }, queryOptions, { transaction: (options || {}).transaction }))
- }
- //right now, the caller (has-many-double-linked) is in charge of the where clause
- DAOFactory.prototype.findAllJoin = function(joinTableName, options, queryOptions) {
- var optcpy = Utils._.clone(options)
- optcpy.attributes = optcpy.attributes || [this.QueryInterface.quoteIdentifier(this.tableName)+".*"]
- // whereCollection is used for non-primary key updates
- this.options.whereCollection = optcpy.where || null;
- return this.QueryInterface.select(this, [this.getTableName(), joinTableName], optcpy, Utils._.defaults({
- type: QueryTypes.SELECT
- }, queryOptions, { transaction: (options || {}).transaction }))
- }
- /**
- * Search for an instance.
- *
- * @param {Object} options Options to describe the scope of the search.
- * @param {Array} include A list of associations which shall get eagerly loaded. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { daoFactory: DaoFactory1, as: 'Alias' } ] }.
- * @param {Object} set the query options, e.g. raw, specifying that you want raw data instead of built DAOs
- * @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
- */
- DAOFactory.prototype.find = function(options, queryOptions) {
- var hasJoin = false
- // no options defined?
- // return an emitter which emits null
- if ([null, undefined].indexOf(options) !== -1) {
- return new Utils.CustomEventEmitter(function(emitter) {
- setTimeout(function() { emitter.emit('success', null) }, 10)
- }).run()
- }
- var primaryKeys = this.primaryKeys
- , keys = Object.keys(primaryKeys)
- , keysLength = keys.length
- , tableNames = { }
- tableNames[this.tableName] = true
- // options is not a hash but an id
- if (typeof options === 'number') {
- var oldOption = options
- options = { where: {} }
- if (keysLength === 1) {
- options.where[keys[0]] = oldOption
- } else {
- options.where.id = oldOption
- }
- } else if (Utils._.size(primaryKeys) && Utils.argsArePrimaryKeys(arguments, primaryKeys)) {
- var where = {}
- Utils._.each(arguments, function(arg, i) {
- var key = keys[i]
- where[key] = arg
- })
- options = { where: where }
- } else if (typeof options === 'string' && parseInt(options, 10).toString() === options) {
- var parsedId = parseInt(options, 10)
- if (!Utils._.isFinite(parsedId)) {
- throw new Error('Invalid argument to find(). Must be an id or an options object.')
- }
- options = { where: parsedId }
- } else if (typeof options === 'object') {
- options = Utils._.clone(options, function(thing) {
- if (Buffer.isBuffer(thing)) { return thing }
- return undefined;
- })
- if (options.hasOwnProperty('include') && options.include) {
- hasJoin = true
- validateIncludedElements.call(this, options, tableNames)
- }
- // whereCollection is used for non-primary key updates
- this.options.whereCollection = options.where || null
- } else if (typeof options === "string") {
- var where = {}
- if (this.primaryKeyCount === 1) {
- where[primaryKeys[keys[0]]] = options;
- options = where;
- } else if (this.primaryKeyCount < 1) {
- // Revert to default behavior which is {where: [int]}
- options = {where: parseInt(Number(options) || 0, 0)}
- }
- }
- options = paranoidClause.call(this, options)
- if (options.limit === undefined) {
- options.limit = 1
- }
- return this.QueryInterface.select(this, this.getTableName(), options, Utils._.defaults({
- plain: true,
- type: QueryTypes.SELECT,
- hasJoin: hasJoin,
- tableNames: Object.keys(tableNames)
- }, queryOptions, { transaction: (options || {}).transaction }))
- }
- DAOFactory.prototype.aggregate = function(field, aggregateFunction, options) {
- var tableField;
- if (field == '*') {
- tableField = field
- } else {
- tableField = this.QueryInterface.QueryGenerator.quoteIdentifier(field)
- }
- options = Utils._.extend({ attributes: [] }, options || {})
- options.attributes.push([aggregateFunction + '(' + tableField + ')', aggregateFunction])
- if (!options.dataType) {
- if (this.rawAttributes[field]) {
- options.dataType = this.rawAttributes[field]
- } else {
- // Use FLOAT as fallback
- options.dataType = DataTypes.FLOAT
- }
- }
- options = paranoidClause.call(this, options)
- return this.QueryInterface.rawSelect(this.getTableName(), options, aggregateFunction)
- }
- DAOFactory.prototype.count = function(options) {
- options = Utils._.clone(options || {})
-
- return new Utils.CustomEventEmitter(function (emitter) {
- var col = this.sequelize.col('*')
- if (options.include) {
- col = this.sequelize.col(this.tableName+'.'+(this.primaryKeyAttributes[0] || 'id'))
- }
- options.attributes = [
- [this.sequelize.fn('COUNT', col), 'count']
- ]
- options.includeIgnoreAttributes = false
- options.limit = null
- this.find(options, {raw: true, transaction: options.transaction}).proxy(emitter, {events: ['sql', 'error']}).success(function (result) {
- var count = (result && result.count) ? parseInt(result.count, 10) : 0
- emitter.emit('success', count)
- })
- }.bind(this)).run()
- }
- DAOFactory.prototype.findAndCountAll = function(findOptions, queryOptions) {
- var self = this
- // no limit, offset, order, attributes for the options given to count()
- , countOptions = Utils._.omit(findOptions ? Utils._.merge({}, findOptions) : {}, ['offset', 'limit', 'order', 'attributes'])
- return new Utils.CustomEventEmitter(function (emitter) {
- var emit = {
- okay : function(count, results) { // emit success
- emitter.emit('success', {
- count: count || 0,
- rows : (results && Array.isArray(results) ? results : [])
- })
- }
- }
- self.count(countOptions)
- .proxy(emitter, {events: ['sql', 'error']})
- .success(function(count) {
- if (count === 0) {
- return emit.okay(count) // no records, no need for another query
- }
- self.findAll(findOptions, queryOptions)
- .proxy(emitter, {events: ['sql', 'error']})
- .success(function(results) {
- emit.okay(count, results)
- })
- })
- }).run()
- }
- DAOFactory.prototype.max = function(field, options) {
- return this.aggregate(field, 'max', options)
- }
- DAOFactory.prototype.min = function(field, options) {
- return this.aggregate(field, 'min', options)
- }
- DAOFactory.prototype.sum = function(field, options) {
- return this.aggregate(field, 'sum', options)
- }
- DAOFactory.prototype.build = function(values, options) {
- options = options || { isNewRecord: true, isDirty: true }
- if (options.hasOwnProperty('include') && options.include && !options.includeValidated) {
- validateIncludedElements.call(this, options)
- }
- return new this.DAO(values, options)
- }
- DAOFactory.prototype.create = function(values, fieldsOrOptions) {
- Utils.validateParameter(values, Object, { optional: true })
- Utils.validateParameter(fieldsOrOptions, Object, { deprecated: Array, optional: true, index: 2, method: 'DAOFactory#create' })
- if (fieldsOrOptions instanceof Array) {
- fieldsOrOptions = { fields: fieldsOrOptions }
- }
- fieldsOrOptions = Utils._.extend({
- transaction: null
- }, fieldsOrOptions || {})
- return this.build(values).save(fieldsOrOptions)
- }
- DAOFactory.prototype.findOrInitialize = DAOFactory.prototype.findOrBuild = function (params, defaults, options) {
- defaults = defaults || {}
- options = options || {}
- var self = this
- , defaultKeys = Object.keys(defaults)
- , defaultLength = defaultKeys.length
- if (!options.transaction && defaults.transaction && (defaults.transaction instanceof Transaction)) {
- options.transaction = defaults.transaction
- delete defaults.transaction
- }
- return new Utils.CustomEventEmitter(function (emitter) {
- self.find({
- where: params
- }, options).success(function (instance) {
- if (instance === null) {
- var i = 0
- for (i = 0; i < defaultLength; i++) {
- params[defaultKeys[i]] = defaults[defaultKeys[i]]
- }
- var build = self.build(params)
- build.hookValidate({skip: Object.keys(params)}).success(function (instance) {
- emitter.emit('success', build, true)
- })
- .error(function (error) {
- emitter.emit('error', error)
- })
- } else {
- emitter.emit('success', instance, false)
- }
- }).error(function (error) {
- emitter.emit('error', error)
- })
- }).run()
- }
- DAOFactory.prototype.findOrCreate = function (where, defaults, options) {
- var self = this
- , values = {}
- options = Utils._.extend({
- transaction: null
- }, options || {})
- if (!(where instanceof Utils.or) && !(where instanceof Utils.and) && !Array.isArray(where)) {
- for (var attrname in where) {
- values[attrname] = where[attrname]
- }
- }
- return new Utils.CustomEventEmitter(function (emitter) {
- self.find({
- where: where
- }, {
- transaction: options.transaction
- }).success(function (instance) {
- if (instance === null) {
- for (var attrname in defaults) {
- values[attrname] = defaults[attrname]
- }
- self
- .create(values, options)
- .success(function (instance) {
- emitter.emit('success', instance, true)
- })
- .error( function (error) {
- emitter.emit('error', error)
- })
- } else {
- emitter.emit('success', instance, false)
- }
- }).error(function (error) {
- emitter.emit('error', error)
- });
- }).run()
- }
- /**
- * Create and insert multiple instances
- *
- * @param {Array} records List of objects (key/value pairs) to create instances from
- * @param {Array} fields Fields to insert (defaults to all fields)
- * @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
- *
- * Note: the `success` handler is not passed any arguments. To obtain DAOs for
- * the newly created values, you will need to query for them again. This is
- * because MySQL and SQLite do not make it easy to obtain back automatically
- * generated IDs and other default values in a way that can be mapped to
- * multiple records
- */
- DAOFactory.prototype.bulkCreate = function(records, fieldsOrOptions, options) {
- Utils.validateParameter(fieldsOrOptions, Object, { deprecated: Array, optional: true, index: 2, method: 'DAOFactory#bulkCreate' })
- Utils.validateParameter(options, 'undefined', { deprecated: Object, optional: true, index: 3, method: 'DAOFactory#bulkCreate' })
- if (!records.length) {
- return new Utils.CustomEventEmitter(function(emitter) {
- emitter.emit('success', [])
- }).run();
- }
- options = Utils._.extend({
- validate: false,
- hooks: false,
- ignoreDuplicates: false
- }, options || {})
- if (fieldsOrOptions instanceof Array) {
- options.fields = fieldsOrOptions
- } else {
- options.fields = options.fields || []
- options = Utils._.extend(options, fieldsOrOptions)
- }
- if(this.daoFactoryManager.sequelize.options.dialect === 'postgres' && options.ignoreDuplicates ) {
- return new Utils.CustomEventEmitter(function(emitter) {
- emitter.emit('error', new Error('Postgres does not support the \'ignoreDuplicates\' option.'))
- }).run();
- }
- var self = this
- , updatedAtAttr = this._timestampAttributes.updatedAt
- , createdAtAttr = this._timestampAttributes.createdAt
- , errors = []
- , daos = records.map(function(v) { return self.build(v) })
- return new Utils.CustomEventEmitter(function(emitter) {
- var done = function() {
- self.runHooks('afterBulkCreate', daos, options.fields, function(err, newRecords, newFields) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- daos = newRecords || daos
- options.fields = newFields || options.fields
- emitter.emit('success', daos, options.fields)
- })
- }
- var next = function() {
- if (options.hooks === false) {
- return runQuery()
- }
- var i = 0
- var iterate = function(i) {
- self.runHooks('beforeCreate', daos[i], function(err, newValues) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- daos[i] = newValues || daos[i]
- daos[i].save({ transaction: options.transaction }).error(function(err) {
- emitter.emit('error', err)
- }).success(function() {
- self.runHooks('afterCreate', daos[i], function(err, newValues) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- daos[i] = newValues || daos[i]
- i++
- if (i >= daos.length) {
- return done()
- }
- iterate(i)
- })
- })
- })
- }
- iterate(i)
- }
- var runQuery = function() {
- // we will re-create from DAOs, which may have set up default attributes
- records = []
- daos.forEach(function(dao) {
- var values = options.fields.length > 0 ? {} : dao.dataValues
- options.fields.forEach(function(field) {
- values[field] = dao.dataValues[field]
- })
- if (createdAtAttr && !values[createdAtAttr]) {
- values[createdAtAttr] = Utils.now(self.daoFactoryManager.sequelize.options.dialect)
- }
- if (updatedAtAttr && !values[updatedAtAttr]) {
- values[updatedAtAttr] = Utils.now(self.daoFactoryManager.sequelize.options.dialect)
- }
- records.push(values)
- })
- self.QueryInterface.bulkInsert(self.tableName, records, options)
- .on('sql', function(sql) {
- emitter.emit('sql', sql)
- })
- .error(function(err) {
- emitter.emit('error', err)
- }).success(function(rows) {
- done()
- })
- }
- self.runHooks('beforeBulkCreate', daos, options.fields, function(err, newRecords, newFields) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- daos = newRecords || daos
- options.fields = newFields || options.fields
- if (options.validate === true) {
- if (options.fields.length) {
- var skippedFields = Utils._.difference(Object.keys(self.attributes), options.fields);
- }
- if (options.hooks === true) {
- var iterate = function(i) {
- daos[i].hookValidate({skip: skippedFields}).error(function(err) {
- errors[errors.length] = {record: v, errors: err}
- i++
- if (i > daos.length) {
- if (errors.length > 0) {
- return emitter.emit('error', errors)
- }
- return next()
- }
- iterate(i)
- })
- }
- } else {
- daos.forEach(function(v) {
- var valid = v.validate({skip: skippedFields})
- if (valid !== null) {
- errors[errors.length] = {record: v, errors: valid}
- }
- })
- if (errors.length > 0) {
- return emitter.emit('error', errors)
- }
- next()
- }
- } else {
- next()
- }
- })
- }).run()
- }
- /**
- * Delete multiple instances
- *
- * @param {Object} where Options to describe the scope of the search.
- * @param {Object} options Possible options are:
- - hooks: If set to true, destroy will find all records within the where parameter and will execute before/afterDestroy hooks on each row
- - limit: How many rows to delete
- - truncate: If set to true, dialects that support it will use TRUNCATE instead of DELETE FROM. If a table is truncated the where and limit options are ignored
- * @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
- */
- DAOFactory.prototype.destroy = function(where, options) {
- options = options || {}
- options.force = options.force === undefined ? false : Boolean(options.force)
- options.type = QueryTypes.BULKDELETE
- var self = this
- , query = null
- , args = []
- return new Utils.CustomEventEmitter(function(emitter) {
- self.runHooks(self.options.hooks.beforeBulkDestroy, where, function(err, newWhere) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- where = newWhere || where
- if (self._timestampAttributes.deletedAt && options.force === false) {
- var attrValueHash = {}
- attrValueHash[self._timestampAttributes.deletedAt] = Utils.now()
- query = 'bulkUpdate'
- args = [self.tableName, attrValueHash, where]
- } else {
- query = 'bulkDelete'
- args = [self.tableName, where, options]
- }
- var runQuery = function(err, records) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- query = self.QueryInterface[query].apply(self.QueryInterface, args)
- query.on('sql', function(sql) {
- emitter.emit('sql', sql)
- })
- .error(function(err) {
- emitter.emit('error', err)
- })
- .success(function(results) {
- var finished = function(err) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- self.runHooks(self.options.hooks.afterBulkDestroy, where, function(err) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- emitter.emit('success', results)
- })
- }
- if (options && options.hooks === true) {
- var tick = 0
- var next = function(i) {
- self.runHooks(self.options.hooks.afterDestroy, records[i], function(err, newValues) {
- if (!!err) {
- return finished(err)
- }
- records[i].dataValues = !!newValues ? newValues.dataValues : records[i].dataValues
- tick++
- if (tick >= records.length) {
- return finished()
- }
- next(tick)
- })
- }
- next(tick)
- } else {
- finished()
- }
- })
- }
- if (options && options.hooks === true) {
- var tick = 0
- self.all({where: where}).error(function(err) { emitter.emit('error', err) })
- .success(function(records) {
- var next = function(i) {
- self.runHooks(self.options.hooks.beforeDestroy, records[i], function(err, newValues) {
- if (!!err) {
- return runQuery(err)
- }
- records[i].dataValues = !!newValues ? newValues.dataValues : records[i].dataValues
- tick++
- if (tick >= records.length) {
- return runQuery(null, records)
- }
- next(tick)
- })
- }
- next(tick)
- })
- //
- } else {
- runQuery()
- }
- })
- }).run()
- }
- /**
- * Update multiple instances
- *
- * @param {Object} attrValueHash A hash of fields to change and their new values
- * @param {Object} where Options to describe the scope of the search.
- * @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
- */
- DAOFactory.prototype.update = function(attrValueHash, where, options) {
- var self = this
- , query = null
- , tick = 0
- options = options || {}
- options.validate = options.validate === undefined ? true : Boolean(options.validate)
- options.hooks = options.hooks === undefined ? false : Boolean(options.hooks)
- options.type = QueryTypes.BULKUPDATE
- if (self._timestampAttributes.updatedAt) {
- attrValueHash[self._timestampAttributes.updatedAt] = Utils.now()
- }
- return new Utils.CustomEventEmitter(function(emitter) {
- var runSave = function() {
- self.runHooks(self.options.hooks.beforeBulkUpdate, attrValueHash, where, function(err, attributes, _where) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- where = _where || where
- attrValueHash = attributes || attrValueHash
- var runQuery = function(err, records) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- query = self.QueryInterface.bulkUpdate(self.tableName, attrValueHash, where, options)
- query.on('sql', function(sql) {
- emitter.emit('sql', sql)
- })
- .error(function(err) {
- emitter.emit('error', err)
- })
- .success(function(results) {
- var finished = function(err, records) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- self.runHooks(self.options.hooks.afterBulkUpdate, attrValueHash, where, function(err) {
- if (!!err) {
- return emitter.emit('error', err)
- }
- emitter.emit('success', records)
- })
- }
- if (options && options.hooks === true && !!records && records.length > 0) {
- var tick = 0
- var next = function(i) {
- self.runHooks(self.options.hooks.afterUpdate, records[i], function(err, newValues) {
- if (!!err) {
- return finished(err)
- }
- records[i].dataValues = !!newValues ? newValues.dataValues : records[i].dataValues
- tick++
- if (tick >= records.length) {
- return finished(null, records)
- }
- next(tick)
- })
- }
- next(tick)
- } else {
- finished(null, results)
- }
- })
- }
- if (options.hooks === true) {
- self.all({where: where}).error(function(err) { emitter.emit('error', err) })
- .success(function(records) {
- if (records === null || records.length < 1) {
- return runQuery(null)
- }
- var next = function(i) {
- self.runHooks(self.options.hooks.beforeUpdate, records[i], function(err, newValues) {
- if (!!err) {
- return runQuery(err)
- }
- records[i].dataValues = !!newValues ? newValues.dataValues : records[i].dataValues
- tick++
- if (tick >= records.length) {
- return runQuery(null, records)
- }
- next(tick)
- })
- }
- next(tick)
- })
- } else {
- runQuery()
- }
- })
- }
- if (options.validate === true) {
- var build = self.build(attrValueHash)
- // We want to skip validations for all other fields
- var updatedFields = Object.keys(attrValueHash)
- var skippedFields = Utils._.difference(Object.keys(self.attributes), updatedFields)
- build.hookValidate({skip: skippedFields}).error(function(err) {
- emitter.emit('error', err)
- }).success(function(attributes) {
- if (!!attributes && !!attributes.dataValues) {
- attrValueHash = Utils._.pick.apply(Utils._, [].concat(attributes.dataValues).concat(Object.keys(attrValueHash)))
- }
- runSave()
- })
- } else {
- runSave()
- }
- }).run()
- }
- DAOFactory.prototype.describe = function(schema) {
- return this.QueryInterface.describeTable(this.tableName, schema || this.options.schema || undefined)
- }
- DAOFactory.prototype.dataset = function() {
- if (!this.__sql) {
- this.__setSqlDialect()
- }
- var instance = this.__sql.define({ name: this.tableName, columns: [] })
- , attributes = this.attributes
- Object.keys(attributes).forEach(function(key) {
- instance.addColumn(key, attributes[key])
- })
- return instance
- }
- DAOFactory.prototype.__setSqlDialect = function() {
- var dialect = this.daoFactoryManager.sequelize.options.dialect
- this.__sql = sql.setDialect(dialect === 'mariadb' ? 'mysql' : dialect)
- }
- // private
- var paranoidClause = function(options) {
- if (this.options.paranoid === true) {
- options = options || {}
- options.where = options.where || {}
- var deletedAtCol = this._timestampAttributes.deletedAt
- , quoteIdentifiedDeletedAtCol = this.QueryInterface.quoteIdentifier(deletedAtCol)
- // Don't overwrite our explicit deletedAt search value if we provide one
- if (!!options.where[deletedAtCol]) {
- return options
- }
- if(this.tableName) {
- quoteIdentifiedDeletedAtCol = this.QueryInterface.quoteIdentifier(this.tableName) + '.' + quoteIdentifiedDeletedAtCol
- }
- if (typeof options.where === "string") {
- options.where += ' AND ' + quoteIdentifiedDeletedAtCol + ' IS NULL '
- }
- else if (Array.isArray(options.where)) {
- // Don't overwrite our explicit deletedAt search value if we provide one
- if(options.where[0].indexOf(deletedAtCol) !== -1) {
- return options
- }
- options.where[0] += ' AND ' + quoteIdentifiedDeletedAtCol + ' IS NULL '
- } else {
- options.where[deletedAtCol] = null
- }
- }
- return options
- }
- var addOptionalClassMethods = function() {
- var self = this
- Utils._.each(this.options.classMethods || {}, function(fct, name) { self[name] = fct })
- }
- var addDefaultAttributes = function() {
- var self = this
- , tail = {}
- , head = {
- id: {
- type: DataTypes.INTEGER,
- allowNull: false,
- primaryKey: true,
- autoIncrement: true,
- _autoGenerated: true
- }
- }
- if (this.hasPrimaryKeys) {
- head = {}
- }
- if (this._timestampAttributes.createdAt) {
- tail[this._timestampAttributes.createdAt] = {type: DataTypes.DATE, allowNull: false}
- }
- if (this._timestampAttributes.updatedAt) {
- tail[this._timestampAttributes.updatedAt] = {type: DataTypes.DATE, allowNull: false}
- }
- if (this._timestampAttributes.deletedAt) {
- tail[this._timestampAttributes.deletedAt] = {type: DataTypes.DATE}
- }
- var existingAttributes = Utils._.clone(self.rawAttributes)
- self.rawAttributes = {}
- Utils._.each(head, function(value, attr) {
- self.rawAttributes[attr] = value
- })
- Utils._.each(existingAttributes, function(value, attr) {
- self.rawAttributes[attr] = value
- })
- Utils._.each(tail, function(value, attr) {
- if (Utils._.isUndefined(self.rawAttributes[attr])) {
- self.rawAttributes[attr] = value
- }
- })
- }
- var findAutoIncrementField = function() {
- var fields = this.QueryGenerator.findAutoIncrementField(this)
- this.autoIncrementField = null
- fields.forEach(function(field) {
- if (this.autoIncrementField) {
- throw new Error('Invalid DAO definition. Only one autoincrement field allowed.')
- } else {
- this.autoIncrementField = field
- }
- }.bind(this))
- }
- var validateIncludedElements = function(options, tableNames) {
- tableNames = tableNames || {}
- options.includeNames = []
- options.includeMap = {}
- options.hasSingleAssociation = false
- options.hasMultiAssociation = false
- // if include is not an array, wrap in an array
- if (!Array.isArray(options.include)) {
- options.include = [options.include]
- }
- // convert all included elements to { daoFactory: Model } form
- var includes = options.include = options.include.map(function(include) {
- if (include instanceof DAOFactory) {
- return { daoFactory: include }
- } else if (typeof include !== 'object') {
- throw new Error('Include unexpected. Element has to be either an instance of DAOFactory or an object.')
- } else if (include.hasOwnProperty('model')) {
- include.daoFactory = include.model
- delete include.model
- }
- return include
- })
- // validate all included elements
- for (var index = 0; index < includes.length; index++) {
- var include = includes[index]
- if (include.all) {
- includes.splice(index, 1)
- index--
- validateIncludedAllElement.call(this, includes, include)
- continue
- }
- include = includes[index] = validateIncludedElement.call(this, include, tableNames)
- include.parent = options
- // associations that are required or have a required child as is not a ?:M association are candidates for the subquery
- include.subQuery = !include.association.isMultiAssociation && (include.hasIncludeRequired || include.required)
- include.hasParentWhere = options.hasParentWhere || !!options.where
- include.hasParentRequired = options.hasParentRequired || !!options.required
- options.includeMap[include.as] = include
- options.includeNames.push(include.as)
- options.includeNames.push(include.as.substr(0,1).toLowerCase() + include.as.substr(1))
- if (include.association.isMultiAssociation || include.hasMultiAssociation) options.hasMultiAssociation = true
- if (include.association.isSingleAssociation || include.hasSingleAssociation) options.hasSingleAssociation = true
- options.hasIncludeWhere = options.hasIncludeWhere || include.hasIncludeWhere || !!include.where
- options.hasIncludeRequired = options.hasIncludeRequired || include.hasIncludeRequired || !!include.required
- }
- }
- var validateIncludedElement = function(include, tableNames) {
- if (!include.hasOwnProperty('daoFactory')) {
- throw new Error('Include malformed. Expected attributes: daoFactory, as!')
- }
- tableNames[include.daoFactory.tableName] = true
- if (include.hasOwnProperty('attributes')) {
- var primaryKeys;
- if (include.daoFactory.hasPrimaryKeys) {
- primaryKeys = []
- for (var field_name in include.daoFactory.primaryKeys) {
- primaryKeys.push(field_name)
- }
- } else {
- primaryKeys = ['id']
- }
- include.attributes = include.attributes.concat(primaryKeys)
- } else {
- include.attributes = Object.keys(include.daoFactory.attributes)
- }
- // pseudo include just needed the attribute logic, return
- if (include._pseudo) return include
- // check if the current daoFactory is actually associated with the passed daoFactory - or it's a pseudo include
- var association = this.getAssociation(include.daoFactory, include.as)
- if (association) {
- include.association = association
- include.as = association.as
- // If through, we create a pseudo child include, to ease our parsing later on
- if (Object(include.association.through) === include.association.through) {
- if (!include.include) include.include = []
- var through = include.association.through
- include.through = {
- daoFactory: through,
- as: Utils.singularize(through.tableName, through.options.language),
- association: {
- isSingleAssociation: true
- },
- _pseudo: true
- }
- include.include.push(include.through)
- tableNames[through.tableName] = true
- }
- if (include.required === undefined) {
- include.required = !!include.where
- }
- // Validate child includes
- if (include.hasOwnProperty('include')) {
- validateIncludedElements.call(include.daoFactory, include, tableNames)
- }
- return include
- } else {
- var msg = include.daoFactory.name
- if (include.as) {
- msg += " (" + include.as + ")"
- }
- msg += " is not associated to " + this.name + "!"
- throw new Error(msg)
- }
- }
- var validateIncludedAllElement = function(includes, include) {
- // check 'all' attribute provided is valid
- var all = include.all
- delete include.all
- if (all !== true) {
- if (!Array.isArray(all)) {
- all = [all]
- }
- var validTypes = {
- BelongsTo: true,
- HasOne: true,
- HasMany: true,
- One: ['BelongsTo', 'HasOne'],
- Has: ['HasOne', 'HasMany'],
- Many: ['HasMany']
- }
- for (var i = 0; i < all.length; i++) {
- var type = all[i]
- if (type == 'All') {
- all = true
- break
- }
- var types = validTypes[type]
- if (!types) {
- throw new Error('include all \'' + type + '\' is not valid - must be BelongsTo, HasOne, HasMany, One, Has, Many or All')
- }
- if (types !== true) {
- // replace type placeholder e.g. 'One' with it's constituent types e.g. 'HasOne', 'BelongsTo'
- all.splice(i, 1)
- i--
- for (var j = 0; j < types.length; j++) {
- if (all.indexOf(types[j]) == -1) {
- all.unshift(types[j])
- i++
- }
- }
- }
- }
- }
- // add all associations of types specified to includes
- var nested = include.nested
- if (nested) {
- delete include.nested
- if (!include.include) {
- include.include = []
- } else if (!Array.isArray(include.include)) {
- include.include = [include.include]
- }
- }
- var used = []
- ;(function addAllIncludes(parent, includes) {
- used.push(parent)
- Utils._.forEach(parent.associations, function(association) {
- if (all !== true && all.indexOf(association.associationType) == -1) {
- return
- }
- // check if model already included, and skip if so
- var model = association.target
- var as = association.options.as
- if (Utils._.find(includes, {daoFactory: model, as: as})) {
- return
- }
- // skip if recursing over a model already nested
- if (nested && used.indexOf(model) != -1) {
- return
- }
- // include this model
- var thisInclude = optClone(include)
- thisInclude.daoFactory = model
- if (as) {
- thisInclude.as = as
- }
- includes.push(thisInclude)
- // run recursively if nested
- if (nested) {
- addAllIncludes(model, thisInclude.include)
- }
- })
- used.pop()
- })(this, includes)
- }
- var replaceReferencesWithTableNames = function(attributes) {
- Object.keys(attributes).forEach(function(attrName) {
- if (attributes[attrName].references instanceof DAOFactory) {
- attributes[attrName].references = attributes[attrName].references.tableName
- }
- })
- return attributes
- }
- var optClone = function (options) {
- return Utils._.cloneDeep(options, function (elem) {
- // The DAOFactories used for include are pass by ref, so don't clone them.
- if (elem instanceof DAOFactory || elem instanceof Utils.col || elem instanceof Utils.literal || elem instanceof Utils.cast || elem instanceof Utils.fn || elem instanceof Utils.and || elem instanceof Utils.or) {
- return elem
- }
- // Unfortunately, lodash.cloneDeep doesn't preserve Buffer.isBuffer, which we have to rely on for binary data
- if (Buffer.isBuffer(elem)) { return elem; }
- // Otherwise return undefined, meaning, 'handle this lodash'
- return undefined
- })
- }
- Utils._.extend(DAOFactory.prototype, require("./associations/mixin"))
- Utils._.extend(DAOFactory.prototype, require(__dirname + '/hooks'))
- return DAOFactory
- })()
|