fknop / hapi-pagination

Hapi plugin to handle "custom" pagination
MIT License
63 stars 36 forks source link

Is this a good way to wrap the pagination logic? #71

Open orditeck opened 6 years ago

orditeck commented 6 years ago

Hi,

I'm using hapipal with lots of their packages. My ORM is schwifty/objection.js. I'm new to the hapi/hapipal stack.

First try

The first thing I noticed is that hapi-pagination doesn't format the results itself because it doesn't know what ORM you're using (https://github.com/fknop/hapi-pagination/issues/11 https://github.com/fknop/hapi-pagination/issues/12).

Objection makes this pretty easy with its page(page, pageSize) method.

So my first draw was this:

'use strict';

module.exports = {
    method: 'GET',
    path: '/clients',
    options: {
        tags: ['api'],
        handler: async (request) => {

            const result = await request
                .models()
                .Clients
                .query()
                .page(request.query.page, request.query.limit);
            request.totalCount = result.total;

            return result;
        }
    }
};

The problem with this is that I'd have to .page(request.query.page, request.query.limit) and request.totalCount = result.total every GET requests where I'd want pagination. I don't like going this way because there are lot of code replication.

Second try

That's where I'd like your advices.

What I did to overcome this is creating a hapijs plugin:

'use strict';

const paginate = async function (query) {

    const result = await query.page(this.request.query.page, this.request.query.limit);
    this.request.totalCount = result.total;

    return this.response(result);
};

exports.plugin = {
    name: 'app-paginate',
    version: '0.1.0',
    register(server, options) {

        server.decorate('toolkit', options.paginateMethod || 'paginate', paginate);
        server.app.paginateMethod = options.paginateMethod;
    }
};

It's a decorator. It automatically finishes the DB request with .page and append the totalCount required for hapi-pagination to the request.

The decorator is called from the route like this:

'use strict';

module.exports = {
    method: 'GET',
    path: '/clients',
    options: {
        tags: ['api'],
        handler: async (request, reply) => {

            return await reply[request.server.app.paginateMethod](
                request.models().Clients.query()
            );
        }
    }
};

reply[request.server.app.paginateMethod](query) translates to reply.appPaginate(query) because server.app.paginateMethod was set previously to options.paginateMethod, and options.paginateMethod is set into the Glue Manifest:

{
    plugin: './plugins/paginate',
    options: {
        paginateMethod: 'appPaginate'
    }
}

Is this second try a good way to achieve my pagination? Maybe there are better ways to do this, I'd like some advices.