UNPKG

apeman-app-rest

Version:
209 lines (186 loc) 5.85 kB
/** * apeman app to handle restful endpoint. * @function apemanAppRest * @param {object} models - Model objects. * @param {object} [options] - Optional settings. * @param {function} [options.pathname='/'+apemanmodel.toType(model)] - Spec path name. * @param {Endpoint|boolean} [options.knock] * @param {Endpoint|boolean} [options.spec] * @param {Endpoint|boolean} [options.list] * @param {Endpoint|boolean} [options.create] * @param {Endpoint|boolean} [options.bulkUpdate] * @param {Endpoint|boolean} [options.bulkDestroy] * @param {Endpoint|boolean} [options.one] * @param {Endpoint|boolean} [options.update] * @param {Endpoint|boolean} [options.destroy] * @param {Endpoint|boolean} [options.relatedList] * @param {Endpoint|boolean} [options.relatedCreate] * @param {Endpoint|boolean} [options.relatedUpdateBulk] * @param {Endpoint|boolean} [options.relatedDestroyBulk] * @param {Endpoint|boolean} [options.relatedOne] * @param {Endpoint|boolean} [options.relatedUpdate] * @param {Endpoint|boolean} [options.relatedDestroy] * @param {Endpoint|boolean} [options.relationList] * @param {Endpoint|boolean} [options.relationCreate] * @param {Endpoint|boolean} [options.relationUpdate] * @param {Endpoint|boolean} [options.relationDestroy] * @returns {function} - Defined app function. */ /** * @typedef {Object} Endpoint * @property {function} handle - Handler function * @property {Object} schema - Validation schema */ 'use strict' const route = require('apeman-app-route') const restSpec = require('./specifying/rest_spec') const assert = require('assert') const co = require('co') const defaults = require('defaults') const apemanmodel = require('apemanmodel') const restRoute = require('./routing/rest_route') const { CreateEndpoint, DestroyEndpoint, Endpoint, ListEndpoint, OneEndpoint, RelatedCreateEndpoint, RelatedDestroyEndpoint, RelatedListEndpoint, RelatedOneEndpoint, RelatedUpdateEndpoint, RelationCreateEndpoint, RelationDestroyEndpoint, RelationListEndpoint, RelationUpdateEndpoint, UpdateEndpoint, SpecEndpoint } = require('./endpoints') const { BulkCreateEndpoint, BulkDestroyEndpoint, BulkRelatedCreateEndpoint, BulkRelatedDestroyEndpoint, BulkRelatedUpdateEndpoint, BulkRelationCreateEndpoint, BulkRelationDestroyEndpoint, BulkUpdateEndpoint } = require('./endpoints/bulk') const debug = require('debug')('apeman:app:rest') /** @lends create */ function create (model, options = {}) { assert.ok(model, 'model is required.') debug(`Register rest for model: ${model}`) let type = apemanmodel.toType(model) let pathname = String(options.pathname || `/${type}`).replace(/\/$/, '') let { associations } = model let { knock, spec, list, create, bulkUpdate, bulkDestroy, one, update, destroy, relatedList, relatedCreate, relatedUpdateBulk, relatedDestroyBulk, relatedOne, relatedUpdate, relatedDestroy, relationList, relationCreate, relationUpdate, relationDestroy } = defaults(options, {}) let rest = restRoute.bind(restRoute, model) let routes = { [`${pathname || '/'}`]: { 'HEAD': rest('knock', knock, true), 'OPTIONS': rest('spec', spec, new SpecEndpoint({ pathname })), 'GET': rest('list', list, new ListEndpoint({}), {}), 'POST': rest('create', create, new CreateEndpoint({})), 'PATCH': rest('bulkUpdate', bulkUpdate, new BulkUpdateEndpoint({})), 'DELETE': rest('bulkDestroy', bulkDestroy, new BulkDestroyEndpoint({})) }, [`${pathname}/:id`]: { 'GET': rest('one', one, new OneEndpoint({})), 'PATCH': rest('update', update, new UpdateEndpoint({})), 'DELETE': rest('destroy', destroy, new DestroyEndpoint({})) } } for (let name of Object.keys(associations || {})) { let association = associations[ name ] let associate = co.wrap(function * associate (ctx, next) { ctx.state.association = association yield next() }) routes[ `${pathname}/:id/${name}` ] = { 'GET': [ associate, ...rest('relatedList', relatedList, new RelatedListEndpoint({})) ], 'POST': [ associate, ...rest('relatedCreate', relatedCreate, new RelatedCreateEndpoint({})) ], 'PATCH': [ associate, ...rest('relatedUpdateBulk', relatedUpdateBulk, new BulkRelatedUpdateEndpoint({})), ], 'DELETE': [ associate, ...rest('relatedDestroyBulk', relatedDestroyBulk, new BulkRelatedDestroyEndpoint({})) ] } routes[ `${pathname}/:id/${name}/:related_id` ] = { 'GET': [ associate, ...rest('relatedOne', relatedOne, new RelatedOneEndpoint({})) ], 'PATCH': [ associate, ...rest('relatedUpdate', relatedUpdate, new RelatedUpdateEndpoint({})) ], 'DELETE': [ associate, ...rest('relatedDestroy', relatedDestroy, new RelatedDestroyEndpoint({})) ] } routes[ `${pathname}/:id/relationships/${name}` ] = { 'GET': [ associate, ...rest('relationList', relationList, new RelationListEndpoint({})) ], 'POST': [ associate, ...rest('relationCreate', relationCreate, new RelationCreateEndpoint({})) ], 'PATCH': [ associate, ...rest('relationUpdate', relationUpdate, new RelationUpdateEndpoint({})) ], 'DELETE': [ associate, ...rest('relationDestroy', relationDestroy, new RelationDestroyEndpoint({})) ] } } let app = route(routes) Object.assign(app, { /** * Application description. */ $desc: 'Restful endpoint.', /** * Endpoint specification. */ $spec: restSpec(model, { pathname }) }) return app } module.exports = create