Lots of Kibana Plugin API Changes in 7.2!

Preface

As Kibana has grown, so has the need for a better plugin architecture. What worked with a few developers and dozens of plugins doesn't scale well to hundreds of developers and hundreds of plugins with dependencies between them. To meet Kibana's needs for the long term, it's clear we need to be thinking about things like (just to name a few): formal plugin contracts that are documented and stable across minor versions; enforcing consistent behavior with patterns like a plugin lifecycle and explicit plugin dependencies; and exposing core services that are technology agnostic, to the extent possible.

In 7.2 we've started rolling out this "new platform". At this point the platform is still experimental, but you'll see new APIs in 7.2 and we will be adding more APIs and stabilizing them over the next few minor releases. You will also see a lot of cleanup and refactoring happening as part of this effort, including the gradual removal of AngularJS in favor of React. Bear with us - it will take some time to roll out the platform and migrate existing plugins, but once all is done Kibana will scale well into the future!

Prefer third-party plugin development in plugins instead of kibana-extra

This change switches preferred third-party plugin development from ../kibana-extra, instead favoring the plugins directory in the Kibana root. By association, @kbn/pm has the --skip-kibana-extra flag renamed to --skip-kibana-plugins.

via #31748

ui/public cleanup

Relocated modules

In preparation for Kibana's upcoming new platform, we are in the process of migrating away from the ui/public directory. Over time, the contents of this directory will be either deprecated or housed inside a parent plugin. If your plugin imports from any of the following ui/public modules, you will need to update your import statements as indicated below, so that you are pulling these modules from their new locations.

ui/search_bar

#35389

// deprecated
import 'ui/search_bar';

// new location
import { data } from 'plugins/data';
data.search.loadLegacyDirectives();

// deprecated
import { SearchBar } from 'ui/public/search_bar/components';

// new location
import { data } from 'plugins/data';
const { SearchBar } = data.search.ui;

ui/query_bar

#35390

// deprecated
import 'ui/query_bar';

// new location
import { data } from 'plugins/data';
data.query.loadLegacyDirectives();

// deprecated
import { QueryBar } from 'ui/public/query_bar/components';

// new location
import { data } from 'plugins/data';
const { QueryBar } = data.query.ui;

via #35683

Expose an HTTP-request browser client

The HTTP browser client now exposes methods for simplifying HTTP requests. The long-term goal of this service/client is to replace the legacy kfetch service. This also swaps out the internals of kfetch for this new service, meaning legacy and new platform plugins are both backed by this functionality.

From a sat up HttpService, there are now 5 additional methods:

  • http.fetch(path, options): This has an API comparable to window.fetch with the addition of a few custom options, status code error handling, default HTTP header additions, and automatic body parsing resolution for JSON and NDJSON.
  • http.get(path, options): The GET-enforced shorthand for http.fetch().
  • http.post(path, options): The POST-enforced shorthand for http.fetch().
  • http.put(path, options): The PUT-enforced shorthand for http.fetch().
  • http.delete(path, options): The DELETE-enforced shorthand for http.fetch().
  • http.patch(path, options): The PATCH-enforced shorthand for http.fetch().

via #35486

Renamed AggParam disabled to shouldShow

In case you're writing a custom AggConfig - which we DO NOT recommend - a parameter could have a disabled callback, which if returning true would hide the control of this parameter in the visualize editor. This callback is now called shouldShow and must return false to be hidden. That way we reduce confusion with controls that can actually have a disabled state.

via #35139

Removed customInterval from AggParam, changed interval value

We removed customInterval from AggParam. Now the custom interval is specified in the interval property. Also now predefined intervals such as Yearly, Daily, etc., are stored as a keys in the interval property, e.g. interval: 'y', interval: 'd', interval: '2s'.

via #34991

Regex AggParam type removed

It is no longer possible to specify an AggParam of type regex. You may be using it when providing your own AggType (which we DO NOT recommend) and consider a stable API. There will be more breaking changes to custom AggTypes in the upcoming versions.

via #34530

Autoload Cleanup & Angular Removal

Removed autoload items

As we work to gradually remove implicit dependencies across the Kibana core, the following items are no longer being imported by ui/autoload. If you use ui/autoload and your plugin relies on any of the following items, please import them explicitly where they are needed.

Removed unused Angular items

In the process of removing Angular from the Kibana core, the following unused items have been deleted. If you have used any of those in your plugin and want to keep using them, please copy over the source from the previous Kibana version directly into your plugin code.

Note: These have also been removed from ui/autoload.

Factories

  • dirtyPrompt, ui/dirty_prompt (via #34060)

Filters

Directives

via #33289

Encourage static i18n import

Kibana is in the process of moving away from AngularJS and as part of that we are starting the process of removing AngularJS specific i18n code.

Going forward, we encourage using i18n.translate() by statically importing i18n from @kbn/i18n wherever possible in your AngularJS code. Avoid using the i18n filter and the i18n service injected in controllers, providers, and services. These will be removed in a future release.

In ReactJS, Avoid using injectI18n and rely on i18n.translate() instead.

via #37858

Get rid of Handlebars support in i18n tools

i18n tooling no longer supports parsing labels from handlebar files. Since we don't use i18n in handlebars in Kibana anymore it'd make sense to get rid of i18n Handlebars support as well. This will make i18n tools code lighter, easier to maintain and slightly improve i18n validation/extraction speed as we'll be skipping .hbs files.

via #32190

npm dependencies

Remove unused pivotal-ui package

via #30975

Upgrade @babel/* dependencies

Updated Babel dependencies as babel has fixed several issues in their TS plugin that allows us to not exclude TS files with some specific syntax from i18n_check that relies on babel/parser and friends.

via #32031

Introduce UI PluginsService

The experimental new platform now supports plugins in the browser. The API for defining plugins mirrors the interface for server-side plugins. New platform plugins can enable a client-side plugin by defining an entry point my_plugin/public/index.ts and adding the "ui": true flag in their my_plugin/kibana.json file.

The entry point for the plugin should export a single plugin function that returns an initialized plugin with the required setup, start, and stop functions:

// my_plugin/public/index.ts
import { CoreSetup, CoreStart, Plugin, PluginInitializer } from 'kibana/public';

export const plugin: PluginInitializer<MyPluginSetup, MyPluginStart> = () =>
  new MyPlugin();

interface MyPluginSetup {
  foo: string;
}

interface MyPluginStart {
  bar(): string;
}

class MyPlugin implements Plugin<MyPluginSetup, MyPluginStart> {
  setup(core: CoreSetup) {
    return { foo: 'bar' };
  }

  start(core: CoreStart) {
    return {
      bar() { return 'baz' }
    };
  }

  stop() { }
}

Any value returned by your plugin's setup and start functions will be provided as dependencies for any plugins that depend on your plugin via the requiredPlugins and optionalPlugins options in a plugin's kibana.json file.

via #32672

Expose New Platform core services to the legacy UI

Kibana is in process of stabilizing the platform APIs. The client side core services are quite different from existing ones and were heavily refactored. If you want to play around with experimental APIs, please use

import { getNewPlatform } from 'ui/new_platform';
const newPlatform = getNewPlatform();

where newPlatform exposes:

via #32480

Expose New Platform core services and plugins contracts to the legacy server

Kibana is in process of stabilizing the platform APIs. During this release, our primary focus was on formalizing API for main core services. Although this is still an experimental API, you can have access to updated elasticsearch and http services on the server side via kbnServer.newPlatform that exposes:

via #32468

Overlay core service

The new (in-development) Kibana Plugin Platform now includes an Overlays service for opening flyouts and modals with EUI. New plugins can access this service via the overlays key on the CoreStart interface passed to plugins in their start lifecycle function. The Overlays service ensures that only a single modal or flyout is present on the page, manages the lifecycle of the overlay, and provides APIs for closing overlays and being notified when the overlay was closed by a user.

via #34261

Restrict import from core & plugin internals for ts files

New platform plugins and core services should have clear boundaries and declare their export contract explicitly. We introduced relevant linter rules in order to enforce this convention and prevent arbitrary exports from module internals. Now import is only allowed:

  • for core service - from the root of the system. src/core/server, src/core/public
  • for plugins - from the root of the plugin. plugins/pluginName/server, plugins/pluginName/public.

via #34688

Added server side API for importing saved objects

New endpoints /api/saved_objects/_import and /api/saved_objects/_resolve_import_errors now exists to import saved objects.

via #32158

Add user_action app for gathering telemetry on user actions

Added a new API endpoint POST /user_action/<app>/<action_type> which is used to add UI telemetry to track user actions. This API that is not intended for external use and will likely change in the next versions.

via #31543

Added server side API for exporting saved objects

A new endpoint /api/saved_objects/_export now exists to export saved objects.

via #30326

Saved Objects

The location of the classes SavedObjectLoader and SavedObjectProvider which are used to load and save saved objects has changed. If you are depending on these classes in your plugin implementation, you have to update the import paths as follows:

  • from import { SavedObjectProvider } from 'ui/courier'; to import { SavedObjectProvider } from 'ui/saved_objects/saved_object';
  • from import { SavedObjectLoader } from 'ui/courier/saved_object/saved_object_loader'; to import { SavedObjectLoader } from 'ui/saved_objects';

via #30241

Introduce Elasticsearch service

We've introduced an Elasticsearch service to the new experimental plugin platform. This service allows new platform plugins to get elasticsearch-js clients for querying Elasticsearch on the server.

To access the new Elasticsearch service from a new platform plugin:

class MyPlugin {
  start(core, plugins) {
    core.elasticsearch.dataClient$.subscribe(client => {
      // query Elasticsearch
    });
  }
}

Clients are exposed via an Observable interface to reflect the possibility that the connection configuration changes while the server is running.

via #28344