UNPKG

merest

Version:

Express based REST-full API for Mongoose models

156 lines (132 loc) 4.91 kB
'use strict'; var express = require('express'); var mongoose = require('mongoose'); var ModelAPIRouter = require('./model-api-router'); var ModelAPIError = require('./model-api-error'); var controllers = require('./controllers'); var middlewares = require('./middlewares'); var path = require('path'); var readMiddlwares = require('./helpers').readMiddlwares; /** * @class ModelAPIExpress - Express application that provides an RESTfull API for different models * * @param {Object} [options] API configuration parameters * @param {String} options.title the title of API <SWAGGER> * @param {String} options.version the version of API <SWAGGER> * @param {String} options.path the path of api root. The application doesn't mount it self on this path. <SWAGGER> * @param {String} options.host the host to reach API. <SWAGGER> * @param {Boolean} [options.options] allows or denies the OPTION end-point on the application level * @param {Function} [options.transformResponse] the function to transform standard response. For details see Transform response * @return {ModelAPIExpress} Created API application */ function ModelAPIExpress(options) { options = options || {}; var app = express(); app.__proto__ = ModelAPIExpress.prototype; app.$__ = {}; app.$__.options = options; app._urls = []; app._urlsDefined = false; app.use(middlewares.registerApi(true, this)); var transformResponse = options.transformResponse instanceof Function ? options.transformResponse : null ; if (transformResponse) { app.use(middlewares.transformResponse(transformResponse)); } app.on('mount', app.__finalize.bind(app)); var __originalListen = app.listen; app.listen = function() { app.__finalize(); return __originalListen.apply(app, arguments); } return app; }; ModelAPIExpress.prototype = Object.create(Function.prototype); ModelAPIExpress.prototype.constructor = ModelAPIExpress; /** * SWAGGER_SUPPORT indicates that the module version supports the swagger */ ModelAPIExpress.prototype.SWAGGER_SUPPORT = true; /** * ModelAPIExpress.prototype.expose - exposes the mongoose model as RESTFull json service * * @param {String} [path] the path to mount exposed model * @param {Function} [middleware] one or more middlewares that should be called before each end-point controller * @param {Mongoose.Model} model Mongoosee model to be exposed * @param {Object} [routerOptions] ModelAPIRouter configuration object (see [Router configuration](configuration.html#router)) * @return {ModelAPIExpress} itself */ ModelAPIExpress.prototype.expose = function(path, middleware, model, routerOptions) { var options, si = 0, ml; path = arguments.length && arguments[0]; if (typeof path === "string") { si = 1; } else { path = null; } var middlewares = readMiddlwares(arguments, si); ml = middlewares && middlewares.length || 0; model = arguments[ml + si]; options = arguments[ml + si + 1] || {}; if (path) { options.path = path } if (ml) { options.middlewares = middlewares } var router = new ModelAPIRouter(model, options); router.attachTo(this); return this; }; /** * ModelAPIExpress.prototype.__attachOptions - attaches the options controller * * @private */ ModelAPIExpress.prototype.__attachOptions = function() { var app = this; var options = app.$__.options; if (options && !(options.options === false) && !options.optionsAttached) { app.options('/', controllers.options.bind(app)); app._urls.push([ 'options', '/', 'List all end-points of current application' ]); options.optionsAttached = true; } } /** * ModelAPIExpress.prototype.urls - returns avaliable list of end-points * * @return {Array} list of end-points */ ModelAPIExpress.prototype.urls = function() { if (this._urlsDefined) return this._urls; if (!this.__routers || !this.__routers.length) return []; this._urlsDefined = true; if (this.mountpath != '/') { for (var i=0; i<this._urls.length; i++) { this._urls[i][1] = path.join(this.mountpath, this._urls[i][1]); } } var router; for (var i=0; i<this.__routers.length; i++) { router = this.__routers[i]; this._urls = this._urls.concat(router.urls(this.mountpath)); } return this._urls; } /** * @private */ ModelAPIExpress.prototype.__addModelAPIrouter = function(router) { this.__routers = this.__routers || []; this.__routers.push(router); } /** * @private */ ModelAPIExpress.prototype.__finalize = function() { this.__attachOptions(); this.use(controllers.notSupported); this.use(controllers.error); this.urls(); } module.exports = exports = ModelAPIExpress;