UNPKG

3.17 kBJavaScriptView Raw
1const Joi = require('joi')
2const Boom = require('boom')
3const errors = require('./errors')
4const validate = require('./validate')
5const header = require('./header')
6const pagination = require('./pagination')
7const pkg = require('../package.json')
8
9/**
10 * @type {Object}
11 * @private
12 *
13 * @description
14 * Store internal objects
15 */
16const internals = {
17 defaults: {
18 total: null,
19 perPage: 100,
20 key: 'result'
21 },
22 scheme: {
23 pluginOptions: Joi.object({
24 absolute: Joi.boolean().default(false),
25 paramNames: Joi
26 .object({
27 perPage: Joi.string().default('per_page'),
28 page: Joi.string().default('page'),
29 total: Joi.string().default('total')
30 })
31 .default({
32 perPage: 'per_page',
33 page: 'page',
34 total: 'total'
35 })
36 })
37 }
38}
39
40/**
41 * @function
42 * @private
43 *
44 * @description
45 * Update schemes based on pluginOption.paramNames
46 *
47 * @param {Object.<string>} paramNames The passed updated paramNames
48 */
49function setParamScheme (paramNames) {
50 internals.scheme = {
51 pluginOptions: internals.scheme.pluginOptions,
52 [paramNames.perPage]: Joi.number()
53 .integer()
54 .min(1)
55 .max(500)
56 .default(100),
57 [paramNames.page]: Joi.number()
58 .integer()
59 .min(1)
60 .default(1)
61 }
62}
63
64/**
65 * @function
66 * @public
67 *
68 * @description
69 * Plugin to generate URIs based on ID and parameters
70 *
71 * @param {Object} server The server to be extended
72 * @param {Object} pluginOptions The plugin options
73 */
74function bissle (server, pluginOptions) {
75 pluginOptions = Joi.attempt(pluginOptions, internals.scheme.pluginOptions)
76
77 const paramNames = pluginOptions.paramNames
78 setParamScheme(paramNames)
79
80 server.expose('scheme', internals.scheme)
81 server.dependency('akaya')
82
83 server.decorate('toolkit', 'bissle', function decorator (res, options) {
84 let result
85 let total
86
87 options = Object.assign({}, internals.defaults, options)
88
89 if (!validate.options(options)) {
90 throw Boom.badRequest(errors.invalidOptions)
91 }
92
93 if (!validate.query(this.request.query, options, pluginOptions.paramNames)) {
94 throw Boom.badRequest(errors.invalidQuery)
95 }
96 const page = this.request.query[paramNames.page]
97 const perPage = this.request.query[paramNames.perPage]
98 const offset = (page - 1) * perPage
99
100 if (options.total !== null) {
101 total = options.total
102 result = res[options.key]
103 } else {
104 total = res[options.key].length
105 result = res[options.key].splice(offset, perPage)
106 }
107
108 const id = this.request.route.settings.id
109
110 if (!id) {
111 throw Boom.badRequest(errors.missingId)
112 }
113
114 const links = pagination.getLinks(
115 id, page, perPage, total, this.request,
116 this.request.aka.bind(this.request), options, pluginOptions
117 )
118
119 const linkHeader = header.getLink(links)
120
121 return this.response(Object.assign(res, {
122 [options.key]: result,
123 _links: links,
124 [paramNames.perPage]: perPage,
125 [paramNames.page]: page,
126 [paramNames.total]: total
127 })).header('link', linkHeader)
128 })
129}
130
131module.exports = {
132 register: bissle,
133 pkg
134}