Skip to content

Dynamic mocks (services)

With the services, we cross some sort of line between pure mocking and an actual alternative backend for our frontend app. But sometimes it can be really useful.

For example when you want to test interactivity in your app, or you don't have the backend yet because you're on a big project with separated teams and the backend will be implemented after the frontend, but you still have to deliver a working frontend at the same time as the backend, etc.

Drosse provides everything you need to implement an interactive mocked backend and let you focus on your frontend usecases.

To define a service, you have to do pretty much the same as to define a static mock. Look at this example where we replace the previous "POST users" inline mock by a service:

routes.json
{
  "api": {
    "users": {
      "DROSSE": {
        "get": {
          "body": [
            { "id": 1, "name": "Jorinho", "premium": false },
            { "id": 2, "name": "Tadai", "premium": true }
          ]
        },
        "post": {
          "service": true
        }
      },
      ":id": {
        "DROSSE": {
          "get": {
            "static": true
          }
        }
      }
    }
  }
}

See? From the routes.json file, it's quite a piece of cake 🍰 !

Now of course, there is no magic (yet!) here. You have to create a file with the proper name and put it in the services subdirectory of your mocks directory.

Info

Like for the others subdirectories, you can redefine the services directory name in your .drosserc.js file (see Configuration).

To name your file, the rule is even simpler as for the static files. Here you just take in account the non-parameter nodes of your route path. In our case we don't have any parameter node. Our POST /api/users route will resolve into a api.users.post.js service file.

Let's just take another example to make it clear. For example for a PUT /api/users/:id/superpowers/:name the service file will be api.users.superpowers.put.js.

Now let's have a look inside these service files.

The service file

A service file must export a function that takes drosse's api object as argument.

services/api.users.get.ts
import { defineDrosseService } from '@jota-one/drosse'

export default defineDrosseService(async ({ event, db }) => {
  // a lot of cool stuffs...
})

As you can see, the object argument gives you access to the well known req and res objects. With those two and the full power of javascript, you can already do more than what you will ever need in a mock-server.

Note

The return value of your function will be passed to the associated route response (optionally modified by a template).

Let's take a full example.

  1. You call POST /api/users and pass this payload: { name: "John" }.
  2. The function in the file services/api.users.post.js is executed.
  3. Let's say it contains this code:
import { defineDrosseService } from '@jota-one/drosse'
import { readBody } from 'h3'

export default defineDrosseService(async ({ event, db }) => {
  const payload = await readBody(event)

  // do whatever you want with your payload
  return { added: payload.name }
})
  1. Your call returns: { added: "John" }.
  2. That's all folks!

Tip

But there is more! The db object gives you access to the embedded Drosse database and its super-fancy API. This part requires a full chapter.