Service

Service

Service is the "glue" for and main interaction point between user and backend. In traditional Model-View-Controller design architecture, it represents Controller.

Service provides methods for user input sanitization, whitelisting and validation. It can be bound to regular Mariner Model or to custom-tailored model. Also, by default it users Mariner Validator, but you can easily replace it with custom one.

Creating and configuring Service

To create a Service, we pass a configuration object.

import { Service } from 'node-mariner';
import UserModel from './models'; // omitted for clarity

const User = new Service({
  name: 'User'
  model: UserModel
});

Configuration Object

Only required properties are model and name.

Basic Service methods

In previous step, we instantiated the service, calling service methods can be done as follows:

const arrayOfUsers = await User.service('find', { name: 'Dan' });

const secondUser = await User.service('findOne', { id: 2 });

const createdUser = await User.service('create', { name: 'Special' });

const updatedUser = await User.service('update', { id: 2, name: 'Updated' });

const deletedUser = await User.service('delete', 2);

const createdOrUpdatedUser = await User.service('upsert', {
  $where: { email: 'dan@radenkovic.org' },
  name: 'D A N'
});

Default Service Methods

Service provides 5 default service methods, though it can be extended or overriden.

Adding, overriding and deleting methods

To extend or override a service with your custom method, just extend the instantiated object:

User.customMethod = function(payload) {
  // some logic here
  return payload
}

// To call it
User.service('customMethod', {hello: true})
export default User;

Deleting (method not allowed):

const User = new Service({ ... });
delete User.create;
export default User

Sanitization

Often, you need to prevent user from sending inappropriate parameters, so you can create a whitelist of allowed params that Service accepts. All other params will be ignored. You need to pass a Configuration object as follows methodName: [Array of accepted fields].

const Post = new Service({
  model,
  name: 'Post',
  sanitize: {
    find: ['body', 'title', 'created_at', 'updated_at', 'user_id'],
    create: ['id', 'title', 'body', 'user_id'],
    update: ['id', 'title', 'body']
  }
});

Post.service('create', { title: 'this will pass', random: 'this will be ignored'})

Sanitization works also for nested structures, for example: const sanitize = { find: ['address.street'] } will allow users to add address object, with street property.

Validation

By default, Service uses validate.js, and all validators can be used.

export default new Service({
  model,
  name: 'Post',
  validate: {
    create: {
      title: { presence: true },
      email: { presence: true, email: true },
      user_id: { presence: true }
    }
  }
});

Replacing default validator and sanitizer

You can replace both validator and sanitizer, by passing custom functions:

export default new Service({
  model,
  name: 'Post',
  validator: (data, constraints) => undefined,
  sanitizer: (data, whitelist, passThru) => data
});

Validator function accepts data and constraints as second argument and should return undefined if data is valid, or to return error object with information about errors.

Sanitizer accepts data, whitelist and passThru. whitelist is an array of allowed fields. passthru is an array of keys that should be ignored in sanitizer if using default Mariner model ($or, $where, etc...).

Emit function

After every successful method, emit function will be called, if provided.

export default new Service({
  model,
  name: 'Post',
  emit: (eventName, payload, params) => {
    // some logic here
  }
});

Function signature has 3 arguments:

  1. eventName, for example, after creating an user, eventName is user:create

  2. payload, data of newly created user (after creation)

  3. params, params used to create an user (before creation)

Last updated