# Services

Services are a set of reusable functions. They are particularly useful to respect the DRY (don’t repeat yourself) programming concept and to simplify controllers logic.

# Implementation

Services can be generated or added manually. Strapi provides a createCoreService factory function that automatically generates core controllers and allows building custom ones or extend/replace the generated controllers.

# Adding a new service

A new service can be implemented:

To manually create a service, export a factory function that returns the service implementation (i.e. an object with methods). This factory function receives the strapi instance:

// path: ./src/api/restaurant/services/restaurant.js

const { createCoreService } = require('@strapi/strapi').factories;

module.exports = createCoreService('api::restaurant.restaurant', ({ strapi }) =>  {
  // Method 1: Creating an entirely custom service
  async exampleService(...args) {
    let response = { okay: true }

    if (response.okay === false) {
      return { response, error: true }
    }

    return response
  },

  // Method 2: Wrapping a core service (leaves core logic in place)
  async find(...args) {  
    // Calling the default core controller
    const { results, pagination } = await super.find(...args);

    // some custom logic
    results.forEach(result => {
      result.counter = 1;
    });

    return { results, pagination };
  },

  // Method 3: Replacing a core service
  async findOne(entityId, params = {}) {
    return strapi.entityService.findOne('api::restaurant.restaurant', entityId, this.getFetchParams(params));
  }
};

πŸ€“ Entity Service API

To get started creating your own services, see Strapi's built-in functions in the Entity Service API documentation.

Example of an email service

The goal of a service is to store reusable functions. An email service could be useful to send emails from different functions in our codebase:

// path: ./src/api/email/services/email.js

const { createCoreService } = require('@strapi/strapi').factories;
const nodemailer = require('nodemailer'); // Requires nodemailer to be installed (npm install nodemailer)

// Create reusable transporter object using SMTP transport.
const transporter = nodemailer.createTransport({
  service: 'Gmail',
  auth: {
    user: 'user@gmail.com',
    pass: 'password',
  },
});

module.exports = createCoreService('api::restaurant.restaurant', ({ strapi }) =>  {
  send(from, to, subject, text) => {
    // Setup e-mail data.
    const options = {
      from,
      to,
      subject,
      text,
    };

    // Return a promise of the function that sends the email.
    return transporter.sendMail(options);
  },
};

The service is now available through the strapi.service('api::email.email').send(...args) global variable. It can be used in another part of the codebase, like in the following controller:

// path: ./src/api/user/controllers/user.js

module.exports = createCoreController('api::restaurant.restaurant', ({ strapi }) =>  {
  // GET /hello
  async signup(ctx) => {
    const { userData } = ctx.body;

    // Store the new user in database.
    const user = await strapi.service('api::users-permissions.user').add(userData);

    // Send an email to validate his subscriptions.
    strapi.service('api::email.email').send('welcome@mysite.com', user.email, 'Welcome', '...');

    // Send response to the server.
    ctx.send({
      ok: true,
    });
  },
};

✏️ NOTE

When a new content-type is created, Strapi builds a generic service with placeholder code, ready to be customized.

# Extending core services

Default services are created for each content-type. These default services are used to execute reusable logic when called throughout your Strapi project and most commonly are used by controllers. Default services can be customized to implement your own logic. The following code examples should help you get started.

πŸ’‘ TIP

A core service can be replaced entirely by creating a custom service and naming it the same as the core service (e.g. find, findOne, create, update, or delete).

Collection type examples
Single type examples

# Usage

Once a service is created, it's accessible from controllers or from other services:

// access an API service
strapi.service('api::apiName.serviceName');
// access a plugin service
strapi.service('plugin::pluginName.serviceName');

πŸ’‘ TIP

To list all the available services, run yarn strapi services:list.