apeman-app-rest
Version:
apeman app to handle restful endpoint.
130 lines (113 loc) • 2.85 kB
JavaScript
/**
* Endpoint for one
* @augments Endpoint
* @class OneEndpoint
*/
const Endpoint = require('./endpoint')
const { toData, defineOne } = require('apemanmodel')
const validateModelExists = require('../validating/validate_model_exists')
const validateInclude = require('../validating/validate_include')
const co = require('co')
/** @lends OneEndpoint */
class OneEndpoint extends Endpoint {
/**
* @override
*/
getDefaultConfig () {
return {
name: 'one'
}
}
/**
* @override
*/
handle (ctx, next) {
const s = this
let succeed = s.bindSucceed(ctx)
let fail = s.bindFail(ctx)
let { state } = ctx
let { model, id, include } = state
let { associations } = model
if (typeof id === 'undefined') {
throw new Error('state.id is required.')
}
return co(function * () {
let error = s.validate(null, state)
if (error) {
return fail(error)
}
let instance = yield s.one(id, state)
let data = toData(model, instance, {
relationships: OneEndpoint.relationships(instance, associations)
})
if (include) {
include.forEach((include) => {
delete data.attributes[ include ]
})
}
return succeed(
{},
data,
{
self: '.'
},
OneEndpoint.included(instance, associations, include)
)
})
}
/**
* @override
*/
validate (data, state) {
let { model, id, instance, include } = state
let includeError = validateInclude(model, include)
if (includeError) {
return includeError
}
let existsError = validateModelExists(model, id, instance)
if (existsError) {
return existsError
}
return null
}
one (id, state) {
const s = this
let { model, transaction, include } = state
let one = defineOne(model, transaction)
return co(function * () {
return yield one(id, include)
})
}
}
Object.assign(OneEndpoint, {
included (found, associations, include) {
let hasInclude = include && (include.length > 0)
if (!hasInclude) {
return undefined
}
return include
.map((name) => {
let association = associations[ name ]
return toData(association.target, found[ name ] || [])
})
.reduce((a, b) => [].concat(a, b), [])
.filter((included) => included)
},
relationships (found, associations) {
let names = associations && Object.keys(associations)
let hasRelationships = names.length > 0
if (!hasRelationships) {
return undefined
}
return names.reduce((result, name) => Object.assign(result, {
[name]: {
links: {
self: `./relationships/${name}/`,
related: `./${name}`
}
}
}), {})
}
})
module.exports = OneEndpoint