@leansdk/leanrc
Version:
LeanRC is a MVC framework for creating graceful applications
140 lines (126 loc) • 5.49 kB
text/coffeescript
# This file is part of LeanRC.
#
# LeanRC is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# LeanRC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with LeanRC. If not, see <https://www.gnu.org/licenses/>.
# миксин подмешивается к классам унаследованным от Module::Resource
# если необходимо переопределить экшен list так чтобы он принимал квери (из браузера) и отдавал не все рекорды в коллекции, а только отфильтрованные
# а также для добавления экшена query который будет использоваться из HttpCollectionMixin'а
module.exports = (Module)->
{
FuncG, StructG, ListG, UnionG, EnumG
ContextInterface
Resource, Mixin
Utils: { _, isArangoDB, joi }
} = Module::
Module.defineMixin Mixin 'QueryableResourceMixin', (BaseClass = Resource) ->
class extends BaseClass
@inheritProtected()
MAX_LIMIT = 50
@public @async writeTransaction: FuncG([String, ContextInterface], Boolean),
default: (asAction, aoContext) ->
result = yield @super asAction, aoContext
if result
if asAction is 'query'
body = if isArangoDB()
aoContext.req.body
else
parse = require 'co-body'
yield parse aoContext.req
{ query } = body ? {}
if query?
key = _.findKey query, (v, k) -> k in [
'$patch', '$remove'
]
result = key?
yield return result
@public @async showNoHiddenByDefault: Function,
default: (args...)->
@listQuery ?= {}
if @listQuery.$filter?
unless /.*\@doc\.isHidden.*/.test JSON.stringify @listQuery.$filter
@listQuery.$filter = $and: [
@listQuery.$filter
,
'@doc.isHidden': no
]
else
@listQuery.$filter = '@doc.isHidden': no
yield return args
@action @async list: FuncG([], StructG {
meta: StructG pagination: StructG {
limit: UnionG Number, EnumG ['not defined']
offset: UnionG Number, EnumG ['not defined']
}
items: ListG Object
}),
default: ->
receivedQuery = _.pick @listQuery, [
'$filter', '$sort', '$limit', '$offset'
]
voQuery = Module::Query.new()
.forIn '@doc': @collection.collectionFullName()
.return '@doc'
if receivedQuery.$filter
do =>
{ error } = joi.validate receivedQuery.$filter, joi.object()
if error?
@context.throw 400, 'ValidationError: `$filter` must be an object', error.stack
voQuery.filter receivedQuery.$filter
if receivedQuery.$sort
do =>
{ error } = joi.validate receivedQuery.$sort, joi.array().items joi.object()
if error?
@context.throw 400, 'ValidationError: `$sort` must be an array'
receivedQuery.$sort.forEach (item)->
voQuery.sort item
if receivedQuery.$limit
do =>
{ error } = joi.validate receivedQuery.$limit, joi.number()
if error?
@context.throw 400, 'ValidationError: `$limit` must be a number', error.stack
voQuery.limit receivedQuery.$limit
if receivedQuery.$offset
do =>
{ error } = joi.validate receivedQuery.$offset, joi.number()
if error?
@context.throw 400, 'ValidationError: `$offset` must be a number', error.stack
voQuery.offset receivedQuery.$offset
limit = Number voQuery.$limit
if @needsLimitation
voQuery.limit switch
when limit > MAX_LIMIT, limit < 0, isNaN limit then MAX_LIMIT
else limit
else unless isNaN limit
voQuery.limit limit
skip = Number voQuery.$offset
voQuery.offset switch
when skip < 0, isNaN skip then 0
else skip
vlItems = yield (yield @collection.query voQuery).toArray()
return {
meta:
pagination:
limit: voQuery.$limit ? 'not defined'
offset: voQuery.$offset ? 'not defined'
items: vlItems
}
@action @async query: FuncG([], Array),
default: ->
{body} = @context.request
return yield (yield @collection.query body.query).toArray()
# ------------ Chains definitions ---------
@chains ['query', 'list']
# @initialHook 'requiredAuthorizationHeader', only: ['query']
@initialHook 'parseBody', only: ['query']
@beforeHook 'showNoHiddenByDefault', only: ['list']
@initializeMixin()