Skip to content

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

@orditeck

Description

@orditeck

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 (#11 #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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions