Skip to content

Instantly share code, notes, and snippets.

@jlsan92
Created October 18, 2017 01:27
Show Gist options
  • Save jlsan92/0e4cc9e66949b5f9a8778a04f91e158c to your computer and use it in GitHub Desktop.
Save jlsan92/0e4cc9e66949b5f9a8778a04f91e158c to your computer and use it in GitHub Desktop.
Mongoose Sails Hook
const _ = require('lodash');
const mongoose = require('mongoose');
const Promise = require('bluebird');
const Schema = mongoose.Schema;
const ORM_NAME = 'mongoose';
module.exports = function mongooseOrm(sails) {
return {
defaults: {
__configKey__: {
connection: {
url: 'mongodb://localhost/test',
options: {},
},
schemas: {
renameFields: { _id: 'id' },
hiddenFields: ['password'],
options: {
versionKey: false,
timestamps: true,
},
},
plugins: [],
},
},
_transform(rename, hidden) {
return {
toJSON(doc, ret) {
_.forEach(hidden, (field) => {
delete ret[field];
});
ret = JSON.stringify(ret);
_.forEach(rename, (newName, oldName) => {
oldName = new RegExp(`"${oldName}":`, 'g');
ret = _.replace(ret, oldName, `"${newName}":`);
});
return JSON.parse(ret);
},
toObject(doc, ret) {
_.forEach(rename, (newName, oldName) => {
ret[newName] = doc[oldName];
});
},
};
},
configure() {
sails.Schema = Schema;
},
initialize(next) {
const config = sails.config[this.configKey];
mongoose.Promise = Promise;
const connection =
mongoose.connect(config.connection.url, config.connection.options).connection;
const self = this;
// Error instantiating mongoose
connection.once('error', (err) => {
sails.log.error(err);
return next(err);
});
// Connected successfully
connection.once('open', () => {
try {
config.plugins.forEach((plugin) => {
const type = typeof plugin;
if (type === 'object' && plugin != null) {
mongoose.plugin(type.plugin, type.options || {});
} else if (type === 'function') {
mongoose.plugin(plugin);
}
});
} catch (e) {
return next(e);
}
// Load model definitions using module loader
return sails.modules.loadModels((err, models) => {
if (err) {
sails.log.error(err);
return next(err);
}
try {
// Expand only mongoose models
if (!sails.models) {
sails.models = {};
}
// Instantiate Mongoose schemas for each model definition
Object.assign(sails.models, _.reduce(models, (result, value, key) => {
if (value.orm !== ORM_NAME) {
return result;
}
value.schema = value.schema || {};
value.plugins = value.plugins || [];
value.options = Object.assign(value.options || {}, config.schemas.options);
// Add default transform to each schema if not defined
if (!value.options.toJSON || !value.options.toJSON.transform) {
const renameFields =
Object.assign(value.renameFields || {}, config.schemas.renameFields);
const hiddenFields = _.union(value.hiddenFields || [], config.schemas.hiddenFields);
const transform = self._transform(renameFields, hiddenFields);
value.options.toJSON = value.options.toJSON || {};
value.options.toJSON.transform = transform.toJSON;
if (!value.options.toObject || !value.options.toObject.transform) {
value.options.toObject = value.options.toObject || {};
value.options.toObject.transform = transform.toObject;
}
}
// Create Mongoose's schema
const schemaObj = new Schema(value.schema, value.options);
schemaObj.statics = value;
schemaObj.methods = value.methods || {};
if (value.indexes) {
value.indexes.forEach(index => schemaObj.index(index.fields, index.options || {}));
}
// Configure existing plugins in current schema
value.plugins.forEach((plugin) => {
const type = typeof plugin;
if (type === 'object' && plugin != null) {
schemaObj.plugin(plugin.plugin, plugin.options || {});
} else if (type === 'function') {
schemaObj.plugin(plugin);
}
});
const collectionName = value.collectionName ?
value.collectionName :
value.globalId;
result[key] = mongoose.model(collectionName, schemaObj);
result[key].globalId = value.globalId;
result[key].identity = value.identity;
return result;
}, {}));
// Expose the models globally
if (_.isObject(sails.config.globals) && sails.config.globals.models) {
_.each(sails.models, (Model, key) => {
if (models[key].orm === ORM_NAME) {
global[Model.globalId] = Model;
}
});
}
return next();
} catch (e) {
return next(e);
}
});
});
},
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment