async init(plugins = {}) {
    this._plugins = new Map([...this.loadPlugins(plugins), ...this._plugins]);

    global.kuzzle.on("plugin:hook:loop-error", ({ error, pluginName }) => {
      global.kuzzle.log.error(
        `[${pluginName}] Infinite loop detected on event "hook:onError": ${error}`,
      );
    });

    global.kuzzle.on("hook:onError", ({ error, event, pluginName }) => {
      global.kuzzle.log.error(
        `[${pluginName}] Error executing hook on "${event}": ${error}${error.stack}`,
      );
    });

    // register regular plugins features
    const loadPlugins = [];
    const defaultImports = {};

    for (const plugin of this._plugins.values()) {
      if (
        this.config.common.failsafeMode &&
        !CORE_PLUGINS.includes(plugin.name)
      ) {
        global.kuzzle.log.info(
          `Failsafe mode activated, skipping plugin "${plugin.name}"`,
        );
        continue;
      }

      if (plugin.application) {
        plugin.init(plugin.name);
      }

      const { initTimeout } = this.config.common;

      debug(
        '[%s] starting plugin in "%s" mode',
        plugin.name,
        plugin.config.privileged ? "privileged" : "standard",
      );

      const promise = Bluebird.resolve(
        (async () => {
          try {
            await plugin.instance.init(plugin.config, plugin.context);
          } catch (error) {
            throw runtimeError.get("failed_init", plugin.name, error);
          }
        })(),
      )
        .timeout(
          initTimeout,
          `${plugin.logPrefix} Initialization timed out after ${initTimeout}ms. Try to increase the configuration "plugins.common.initTimeout".`,
        )
        .then(async () => {
          plugin.initCalled = true;

          if (
            !_.isEmpty(plugin.instance.controllers) &&
            !_.isEmpty(plugin.instance.api)
          ) {
            throw assertionError.get("duplicated_api_definition");
          }

          if (!_.isEmpty(plugin.instance.controllers)) {
            this._initControllers(plugin);
          }

          if (!_.isEmpty(plugin.instance.api)) {
            await this._initApi(plugin);
          }

          if (!_.isEmpty(plugin.instance.authenticators)) {
            this._initAuthenticators(plugin);
          }

          if (!_.isEmpty(plugin.instance.strategies)) {
            this._initStrategies(plugin);
          }

          if (!_.isEmpty(plugin.instance.hooks)) {
            this._initHooks(plugin);
          }

          if (!_.isEmpty(plugin.instance.pipes)) {
            this._initPipes(plugin);
          }

          debug("[%s] plugin started", plugin.name);

          if (!plugin.application) {
            this.loadedPlugins.push(plugin.name);
          }

          if (!_.isEmpty(plugin.instance.imports)) {
            _.merge(defaultImports, plugin.instance.imports);
          }

          return null;
        });

      loadPlugins.push(promise);
    }

    await Promise.all(loadPlugins);

    return defaultImports;
  }
Register plugins feature to Kuzzle

@returns {Promise}

@throws PluginImplementationError - Throws when an error occurs when registering a plugin