# Server API for plugins

A Strapi plugin can interact with the back end or the front end of the Strapi application. The Server API is about the back end part.

Creating and using a plugin interacting with the Server API consists of 2 steps:

  1. Declare and export the plugin interface within the strapi-server.js entry file
  2. Use the exported interface

# Entry file

To tap into the Server API, create a strapi-server.js file at the root of the plugin package folder. This file exports the required interface, with the following parameters available:

Parameter type Available parameters
Lifecycle functions
Configuration config object
Backend customizations

# Lifecycle functions

# register()

This function is called to load the plugin, even before the application is actually bootstrapped, in order to register permissions or database migrations.

Type: Function

Example:

// path ./strapi-server.js

module.exports = () => ({
  register({ strapi }) {
    // execute some register code
  },
});

# bootstrap()

The bootstrap function is called right after the plugin has registered.

Type: Function

Example:

// path: ./strapi-server.js

module.exports = () => ({
  bootstrap({ strapi }) {
    // execute some bootstrap code
  },
});

# destroy()

The destroy lifecycle function is called to cleanup the plugin (close connections, remove listeners…) when the Strapi instance is destroyed.

Type: Function

Example:

// path: ./strapi-server.js

module.exports = () => ({
  destroy({ strapi }) {
    // execute some destroy code
  },
});

# Configuration

config stores the default plugin configuration.

Type: Object

Parameter Type Description
default Object, or Function that returns an Object Default plugin configuration, merged with the user configuration
validator Function
  • Checks if the results of merging the default plugin configuration with the user configuration is valid
  • Throws errors when the resulting configuration is invalid

Example:

// path: ./strapi-server.js

const config = require('./config');

module.exports = () => ({
  config: {
    default: ({ env }) => ({ optionA: true }),
    validator: (config) => { 
      if (typeof config.optionA !== 'boolean') {
        throw new Error('optionA has to be a boolean');
      }
    },
  },
});

# Backend customization

# Content-Types

An object with the Content-Types the plugin provides.

Type: Object

✏️ NOTE

Content-Types keys in the contentTypes object should re-use the singularName defined in the info key of the schema.

Example:

// path: ./strapi-server.js

const contentTypes = require('./content-types');

module.exports = () => ({
  contentTypes,
});
// path: ./content-types/index.js

const contentTypeA = require('./content-type-a');
const contentTypeB = require('./content-type-b');

module.exports = {
  'content-type-a': { schema: contentTypeA }, // should re-use the singularName of the content-type
  'content-type-b': { schema: contentTypeB },
};
// path: ./content-types/content-type-a.js

module.exports = {
  info: {
    tableName: 'content-type',
    singularName: 'content-type-a', // kebab-case mandatory
    pluralName: 'content-type-as', // kebab-case mandatory
    displayName: 'Content Type A',
    description: 'A regular content type',
    kind: 'collectionType',
  },
  options: {
    draftAndPublish: true,
  },
  pluginOptions: {
    'content-manager': {
      visible: false,
    },
    'content-type-builder': {
      visible: false,
    }
  },
  attributes: {
    name: {
      type: 'string',
      min: 1,
      max: 50,
      configurable: false,
    },
  }
};

# Routes

An array of routes configuration.

Type: Object[]

Example:

// path: ./strapi-server.js

const routes = require('./routes');

module.exports = () => ({
  routes,
  type: 'content-api', // can also be 'admin-api' depending on the type of route
});
// path: ./routes/index.js

module.exports = [
  {
    method: 'GET',
    path: '/model',
    handler: 'controllerName.action',
    config: {
      policies: ['policyName'],
    },
  },
];

# Controllers

An object with the controllers the plugin provides.

Type: Object

Example:

// path: ./strapi-server.js

const controllers = require('./controllers');

module.exports = () => ({
  controllers,
});
// path: ./controllers/index.js

const controllerA = require('./controller-a');
const controllerB = require('./controller-b');

module.exports = {
  controllerA,
  controllerB,
};
// path: ./controllers/controller-a.js

module.exports = ({ strapi }) => ({
  doSomething(ctx) {
    ctx.body = { message: 'HelloWorld' };
  },
});

# Services

An object with the services the plugin provides.

Services should be functions taking strapi as a parameter.

Type: Object

Example:

// path: ./strapi-server.js

const services = require('./services');

module.exports = () => ({
  services,
});
// path: ./services/index.js

const serviceA = require('./service-a');
const serviceB = require('./service-b');

module.exports = {
  serviceA,
  serviceB,
};
// path: ./services/service-a.js

module.exports = ({ strapi }) => ({
  someFunction() {
    return [1, 2, 3];
  },
});

# Policies

An object with the policies the plugin provides.

Type: Object

Example:

// path: ./strapi-server.js

const policies = require('./policies');

module.exports = () => ({
  policies,
});
// path: ./policies/index.js

const policyA = require('./policy-a');
const policyB = require('./policy-b');

module.exports = {
  policyA,
  policyB,
};
// path: ./policies/policy-a.js

module.exports = (policyContext, config, { strapi }) => {
    if (ctx.state.user && ctx.state.user.isActive) {
      return true;
    }

    return false;
  },
};

# Middlewares

An object with the middlewares the plugin provides.

Type: Object

Example:

// path: ./strapi-server.js

const middlewares = require('./middlewares');
module.exports = () => ({
  middlewares,
});
// path: ./middlewares/index.js

const middlewareA = require('./middleware-a');
const middlewareB = require('./middleware-b');

module.exports = {
  middlewareA,
  middlewareB,
};
// path: ./middlewares/middleware-a.js

module.exports = (options, { strapi }) => {
 return async (ctx, next) => {
    const start = Date.now();
    await next();
    const delta = Math.ceil(Date.now() - start);

    strapi.log.http(`${ctx.method} ${ctx.url} (${delta} ms) ${ctx.status}`);
 };
};

# Usage

Once a plugin is exported and loaded into Strapi, its features are accessible in the code through getters. The Strapi instance (strapi) exposes top-level getters and global getters.

While top-level getters imply chaining functions, global getters are syntactic sugar that allows direct access using a feature's uid:

// Access an API or a plugin controller using a top-level getter 
strapi.api['api-name'].controller('controller-name')
strapi.plugin('plugin-name').controller('controller-name')

// Access an API or a plugin controller using a global getter
strapi.controller('api::api-name.controller-name')
strapi.controller('plugin::plugin-name.controller-name')
Top-level getter syntax examples
strapi.plugin('plugin-name').config
strapi.plugin('plugin-name').routes
strapi.plugin('plugin-name').controller('controller-name')
strapi.plugin('plugin-name').service('service-name')
strapi.plugin('plugin-name').contentType('content-type-name')
strapi.plugin('plugin-name').policy('policy-name')
strapi.plugin('plugin-name').middleware('middleware-name')
Global getter syntax examples
strapi.controller('plugin::plugin-name.controller-name');
strapi.service('plugin::plugin-name.service-name');
strapi.contentType('plugin::plugin-name.content-type-name');
strapi.policy('plugin::plugin-name.policy-name');
strapi.middleware('plugin::plugin-name.middleware-name');