Search code examples
loopbackjsstrongloopservice-layer

Best Practice : Service Layer in Loopback


I am building an application in loopback and wondering how to build a service layer with an API which is not related to any model. Here is my scenario.

I have a two models User, Game, UserGames. UserGames is a many-to-many relation and stores the score of users in different games. I want to provide an API for weeklyLeaderboard but I don't want it to be a Remote Method for any of the my models as it doesn't fit the RESTful API guidelines.

The only way I can find to implement right now is to create a service common/service/weeklyLeaderboard.js and a route in server/boot/routes.js which accesses this service. In that case, I would have to re-arrange the middlewares in my middleware.json to have non remote-method end-points treated in the same way as remote methods and have access to the currentContext.

Is there a better way to implement APIs which are not related to a specific model but access several data-access and business objects.


Solution

  • Disclaimer: I am a co-author and an active maintainer of LoopBack.

    In our recently released LoopBack version 4, we have decoupled REST APIs from the database access. REST APIs are implemented by Controller classes, data structures are described by Models and database is accessed via Repositories. This makes it easy to write a service layer that's decoupled from data-access details.

    In LoopBack 3, I recommend to create a new model (e.g. Leaderboard) and treat it as a controller. There are two tricks needed to make it work:

    • Inherit from Model, not the default PersistedModel. That way your controller-like model starts empty, with no (built-in) remote methods.
    • Don't attach your controller-like model to any datasource. In server/model-config.json, set the dataSource entry of your new model to null.

    Then you can define your weeklyLeaderboard endpoint as a regular remote method and get all benefits offered by LoopBack, e.g. your new endpoint will be included in the generated Swagger spec and testable via API Explorer.