mongoose-super
Version:
Augments Mongoose.js models with super() to call parent model methods. Augmentation is done in an inherit() function that returns a child model based on a parent model and a child schema.
173 lines (144 loc) • 5.11 kB
JavaScript
/**
* Created by Freddy Snijder on 17/04/16.
*/
/**********************************************************
*
* UTILITIES
*
**********************************************************/
var toString = Object.prototype.toString;
var _u = {
obj : function(o) {
return ('[object Object]' == toString.call(o));
},
func : function(f) {
return (typeof f === "function");
},
array : function(a) {
return (toString.call(a) == '[object Array]');
},
hasMethod : function(o, methodName) {
return (this.obj(o) || this.func(o) || this.array(o)) && this.func(o[methodName]);
},
string : function(s) {
return typeof s === "string";
},
modelName : function(m) {
var type = typeof m;
if ((type !== "function") && (type !== "object")) {
return "[UNKNOWN MODEL]";
}
var c = m.constructor || {};
return c.modelName || "[UNKNOWN MODEL]";
}
};
/**********************************************************
*
* END UTILITIES
*
**********************************************************/
// In the future this could provide different super() methods based on some context (e.g. Mongoose.js version)
function __createSuper(config) {
config = config || {};
var _l = config.logger;
if (!_l) {
_l = console;
}
return function(methodName) {
var self = this;
var pp = this.__npm_mongoose_super_proto_proto;
if (!pp) {
pp = this.__proto__ || {};
pp = pp.__proto__ || {};
this.__npm_mongoose_super_proto_proto = pp;
}
var methodList = this.__npm_mongoose_super_method_list || {};
var method = methodList[methodName];
if (!method) {
method = pp[methodName];
if (!_u.func(method)) {
return function() {
_l.error("mongoose-super::super", "Error : Parent model of " + _u.modelName(self) +
" has no method '" + methodName +"'");
}
}
method = method.bind(this);
methodList[methodName] = method;
this.__npm_mongoose_super_method_list = methodList;
}
return method;
};
}
/**
*
* Creates inherit function
*
* Usage :
* var inherit = MongooseSuper();
* // ... OR ..
* var inherit = MongooseSuper({
* logger : myLogger
* });
*
* var ChildModel = inherit(ParentModel, childModelName, childSchemaExtension[, childModelOptions]);
*
*
* @param {object} [config] Optional configuration object
* @param {object} [config.logger=console] Optional external logger object
*
* @returns {function|null} On success returns inherit function
*
*/
var createInherit = function(config) {
var me = "mongoose-super::createInherit";
config = config || {};
var _l = config.logger;
if (!_u.obj(_l)) {
_l = console;
}
var __super = __createSuper(config);
if (!_u.func(__super)) {
_l.error(me,
"Error: Unable to create super method, setup of mongoose-super failed ...");
return function() {
_l.error(
"mongoose-super::inherit",
"Error: Setup of mongoose-super failed, unable to create child model ...");
}
}
var __inherit = function(ParentModel, childModelName, ChildSchemaExtension, childModelOptions) {
var me = "mongoose-super::inherit";
if ((!_u.string(childModelName)) || (childModelName.length == 0)) {
_l.error(me, "Error: Given child model name is not a string or empty, " +
"unable to create child model");
return null;
}
if (!_u.hasMethod(ParentModel, "discriminator")) {
_l.error(me, "Error: Given parent model is undefined or has no discriminator method, " +
"unable to create child model " + childModelName);
return null;
}
if (!_u.obj(ChildSchemaExtension)) {
_l.error(me, "Error: No valid ChildSchemaExtension given, " +
"unable to create child model " + childModelName +
" of " + _u.modelName(ParentModel));
return null;
}
try {
var ChildModel = ParentModel.discriminator(childModelName, ChildSchemaExtension, childModelOptions);
if (_u.func(ChildModel)) {
ChildModel.prototype.super = __super;
} else {
_l.error(me, "Error: UNEXPECTED : Creation failed of child model " + childModelName +
" of " + _u.modelName(ParentModel));
}
} catch(e) {
_l.error(me, "Error: An exception occurred trying to create child model " + childModelName +
" of " + _u.modelName(ParentModel) + " : ", e, e.stack);
}
return ChildModel;
};
return __inherit;
};
module.exports._u = _u;
module.exports.createInherit = createInherit;