[[migrating-legacy-plugins]]
== Migrating legacy plugins to the {kib} Platform

[IMPORTANT]
==============================================
In {kib} 7.10, support for legacy-style {kib} plugins was completely removed.
Moving forward, all plugins must be built on the new {kib} Platform Plugin API.
This guide is intended to assist plugin authors in migrating their legacy plugin
to the {kib} Platform Plugin API.
==============================================

Make no mistake, it is going to take a lot of work to move certain
plugins to the {kib} Platform.

The goal of this document is to guide developers through the recommended
process of migrating at a high level. Every plugin is different, so
developers should tweak this plan based on their unique requirements.

First, we recommend you read <<kibana-platform-plugin-api>> to get an overview
of how plugins work in the {kib} Platform. Then continue here to follow our
generic plan of action that can be applied to any legacy plugin.

=== Challenges to overcome with legacy plugins

{kib} Platform plugins have an identical architecture in the browser and on
the server. Legacy plugins have one architecture that they use in the
browser and an entirely different architecture that they use on the
server.

This means that there are unique sets of challenges for migrating to the
{kib} Platform, depending on whether the legacy plugin code is on the
server or in the browser.

==== Challenges on the server

The general architecture of legacy server-side code is similar to
the {kib} Platform architecture in one important way: most legacy
server-side plugins define an `init` function where the bulk of their
business logic begins, and they access both `core` and
`plugin-provided` functionality through the arguments given to `init`.
Rarely does legacy server-side code share stateful services via import
statements.

Although not exactly the same, legacy plugin `init` functions behave
similarly today as {kib} Platform `setup` functions. `KbnServer` also
exposes an `afterPluginsInit` method, which behaves similarly to `start`.
There is no corresponding legacy concept of `stop`.

Despite their similarities, server-side plugins pose a formidable
challenge: legacy core and plugin functionality is retrieved from either
the hapi.js `server` or `request` god objects. Worse, these objects are
often passed deeply throughout entire plugins, which directly couples
business logic with hapi. And the worst of it all is, these objects are
mutable at any time.

The key challenge to overcome with legacy server-side plugins will
decoupling from hapi.

==== Challenges in the browser

The legacy plugin system in the browser is fundamentally incompatible
with the {kib} Platform. There is no client-side plugin definition. There
are no services that get passed to plugins at runtime. There really
isn’t even a concrete notion of `core`.

When a legacy browser plugin needs to access functionality from another
plugin, say to register a UI section to render within another plugin, it
imports a stateful (global singleton) JavaScript module and performs
some sort of state mutation. Sometimes this module exists inside the
plugin itself, and it gets imported via the `plugin/` webpack alias.
Sometimes this module exists outside the context of plugins entirely and
gets imported via the `ui/` webpack alias. Neither of these concepts
exists in the {kib} Platform.

Legacy browser plugins rely on the feature known as `uiExports/`, which
integrates directly with our build system to ensure that plugin code is
bundled together in such a way to enable that global singleton module
state. There is no corresponding feature in the {kib} Platform, and in
the fact we intend down the line to build {kib} Platform plugins as immutable
bundles that can not share state in this way.

The key challenge to overcome with legacy browser-side plugins will be
converting all imports from `plugin/`, `ui/`, `uiExports`, and relative
imports from other plugins into a set of services that originate at
runtime during plugin initialization and get passed around throughout
the business logic of the plugin as function arguments.

==== Plan of action

To move a legacy plugin to the new plugin system, the
challenges on the server and in the browser must be addressed.

The approach and level of effort varies significantly between server and
browser plugins, but at a high level, the approach is the same.

First, decouple your plugin’s business logic from the dependencies that
are not exposed through the {kib} Platform, hapi.js, and Angular.js. Then
introduce plugin definitions that more accurately reflect how plugins
are defined in the {kib} Platform. Finally, replace the functionality you
consume from the core and other plugins with their {kib} Platform equivalents.

Once those things are finished for any given plugin, it can officially
be switched to the new plugin system.

=== Server-side plan of action

Legacy server-side plugins access functionality from the core and other
plugins at runtime via function arguments, which is similar to how they
must be architected to use the new plugin system. This greatly
simplifies the plan of action for migrating server-side plugins.
The main challenge here is to de-couple plugin logic from hapi.js server and request objects.

For migration examples, see <<migrating-legacy-plugins-examples>>.

=== Browser-side plan of action

It is generally a much greater challenge preparing legacy browser-side
code for the {kib} Platform than it is server-side, and as such there are
a few more steps. The level of effort here is proportional to the extent
to which a plugin is dependent on Angular.js.

To complicate matters further, a significant amount of the business
logic in {kib} client-side code exists inside the `ui/public`
directory (aka ui modules), and all of that must be migrated as well.

Because the usage of Angular and `ui/public` modules varies widely between
legacy plugins, there is no `one size fits all` solution to migrating
your browser-side code to the {kib} Platform.

For migration examples, see <<migrating-legacy-plugins-examples>>.

=== Frequently asked questions

==== Do plugins need to be converted to TypeScript?

No. That said, the migration process will require a lot of refactoring,
and TypeScript will make this dramatically easier and less risky.

Although it's not strictly necessary, we encourage any plugin that exposes an extension point to do so
with first-class type support so downstream plugins that _are_ using
TypeScript can depend on those types.

==== How can I avoid passing core services deeply within my UI component tree?

Some core services are purely presentational, for example
`core.overlays.openModal()`, where UI
code does need access to these deeply within your application. However,
passing these services down as props throughout your application leads
to lots of boilerplate. To avoid this, you have three options:

* Use an abstraction layer, like Redux, to decouple your UI code from
core (*this is the highly preferred option*).
* https://github.com/reduxjs/redux-thunk#injecting-a-custom-argument[redux-thunk]
and
https://redux-saga.js.org/docs/api/#createsagamiddlewareoptions[redux-saga]
already have ways to do this.
* Use React Context to provide these services to large parts of your
React tree.
* Create a high-order-component that injects core into a React
component.
* This would be a stateful module that holds a reference to core, but
provides it as props to components with a `withCore(MyComponent)`
interface. This can make testing components simpler. (Note: this module
cannot be shared across plugin boundaries, see above).
* Create a global singleton module that gets imported into each module
that needs it. This module cannot be shared across plugin
boundaries.
https://gist.github.com/epixa/06c8eeabd99da3c7545ab295e49acdc3[Example].

If you find that you need many different core services throughout your
application, this might indicate a problem in your code and could lead to pain down the
road. For instance, if you need access to an HTTP Client or
SavedObjectsClient in many places in your React tree, it’s likely that a
data layer abstraction (like Redux) could make developing your plugin
much simpler.

Without such an abstraction, you will need to mock out core services
throughout your test suite and will couple your UI code very tightly to
core. However, if you can contain all of your integration points with
core to Redux middleware and reducers, you only need to mock core
services once and benefit from being able to change those integrations
with core in one place rather than many. This will become incredibly
handy when core APIs have breaking changes.

==== How is the 'common' code shared on both the client and the server?

There is no formal notion of `common` code that can safely be imported
from either client-side or server-side code. However, if a plugin author
wishes to maintain a set of code in their plugin in a single place and
then expose it to both server-side and client-side code, they can do so
by exporting the index files for both the `server` and `public`
directories.

Plugins _should not_ ever import code from deeply inside another plugin
(e.g. `my_plugin/public/components`) or from other top-level directories
(e.g. `my_plugin/common/constants`) as these are not checked for breaking
changes and are considered unstable and subject to change at any time.
You can have other top-level directories like `my_plugin/common`, but
our tooling will not treat these as a stable API, and linter rules will
prevent importing from these directories _from outside the plugin_.

The benefit of this approach is that the details of where code lives and
whether it is accessible in multiple runtimes is an implementation
detail of the plugin itself. A plugin consumer that is writing
client-side code only ever needs to concern themselves with the
client-side contracts being exposed, and the same can be said for
server-side contracts on the server.

A plugin author, who decides some set of code should diverge from having
a single `common` definition, can now safely change the implementation
details without impacting downstream consumers.

==== How do I find {kib} Platform services?

Most of the utilities you used to build legacy plugins are available
in the {kib} Platform or {kib} Platform plugins. To help you find the new
home for new services, use the tables below to find where the {kib}
Platform equivalent lives.

===== Client-side
====== Core services

In client code, `core` can be imported in legacy plugins via the
`ui/new_platform` module.

[[client-side-core-migration-table]]
[width="100%",cols="15%,85%",options="header",]
|===
|Legacy Platform |{kib} Platform
|`chrome.addBasePath`
|{kib-repo}/tree/{branch}/docs/development/core/public/kibana-plugin-core-public.ibasepath.md[`core.http.basePath.prepend`]

|`chrome.breadcrumbs.set`
|{kib-repo}/tree/{branch}/docs/development/core/public/kibana-plugin-core-public.chromestart.setbreadcrumbs.md[`core.chrome.setBreadcrumbs`]

|`chrome.getUiSettingsClient`
|{kib-repo}/tree/{branch}/docs/development/core/public/kibana-plugin-core-public.corestart.uisettings.md[`core.uiSettings`]

|`chrome.helpExtension.set`
|{kib-repo}/tree/{branch}/docs/development/core/public/kibana-plugin-core-public.chromestart.sethelpextension.md[`core.chrome.setHelpExtension`]

|`chrome.setVisible`
|{kib-repo}/tree/{branch}/docs/development/core/public/kibana-plugin-core-public.chromestart.setisvisible.md[`core.chrome.setIsVisible`]

|`chrome.getInjected`
| Request Data with your plugin REST HTTP API.

|`chrome.setRootTemplate` / `chrome.setRootController`
|Use application mounting via {kib-repo}/tree/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationsetup.register.md[`core.application.register`]

|`chrome.navLinks.update`
|{kib-repo}/tree/{branch}/docs/development/core/public/kibana-plugin-core-public.app.updater_.md[`core.appbase.updater`]. Use the `updater$` property when registering your application via
`core.application.register`

|`import { recentlyAccessed } from 'ui/persisted_log'`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.chromerecentlyaccessed.md[`core.chrome.recentlyAccessed`]

|`ui/capabilities`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.capabilities.md[`core.application.capabilities`]

|`ui/documentation_links`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md[`core.docLinks`]

|`ui/kfetch`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.httpsetup.md[`core.http`]

|`ui/notify`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.notificationsstart.md[`core.notifications`]
and
{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.overlaystart.md[`core.overlays`]. Toast messages are in `notifications`, banners are in `overlays`.

|`ui/routes`
|There is no global routing mechanism. Each app
{kib-repo}blob/{branch}/rfcs/text/0004_application_service_mounting.md#complete-example[configures
its own routing].

|`ui/saved_objects`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.savedobjectsstart.md[`core.savedObjects`]

|`ui/doc_title`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.chromedoctitle.md[`core.chrome.docTitle`]

|`uiExports/injectedVars` / `chrome.getInjected`
|<<configuration-service, Configuration service>>. Can only be used to expose configuration properties
|===

_See also:
{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.corestart.md[Public’s
CoreStart API Docs]_

====== Plugins for shared application services

In client code, we have a series of plugins that house shared
application services, which are not technically part of `core`, but are
often used in {kib} plugins.

This table maps some of the most commonly used legacy items to their {kib}
Platform locations. For the API provided by {kib} Plugins see <<plugin-list, the plugin list>>.

[width="100%",cols="15,85",options="header"]
|===
|Legacy Platform |{kib} Platform
|`import 'ui/apply_filters'` |N/A. Replaced by triggering an
{kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.action_global_apply_filter.md[APPLY_FILTER_TRIGGER trigger]. Directive is deprecated.

|`import 'ui/filter_bar'`
|`import { FilterBar } from 'plugins/data/public'`. Directive is deprecated.

|`import 'ui/query_bar'`
|`import { QueryStringInput } from 'plugins/data/public'` {kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md[QueryStringInput]. Directives are deprecated.

|`import 'ui/search_bar'`
|`import { SearchBar } from 'plugins/data/public'` {kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.searchbar.md[SearchBar]. Directive is deprecated.

|`import 'ui/kbn_top_nav'`
|`import { TopNavMenu } from 'plugins/navigation/public'`. Directive was removed.

|`ui/saved_objects/saved_object_finder`
|`import { SavedObjectFinder } from 'plugins/saved_objects/public'`

|`core_plugins/interpreter`
|{kib-repo}blob/{branch}/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.md[`plugins.data.expressions`]

|`ui/courier`
|{kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginsetup.search.md[`plugins.data.search`]

|`ui/agg_types`
|{kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.aggs.md[`plugins.data.search.aggs`]. Most code is available for
static import. Stateful code is part of the `search` service.

|`ui/embeddable`
|{kib-repo}blob/{branch}/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.md[`plugins.embeddables`]

|`ui/filter_manager`
|`import { FilterManager } from 'plugins/data/public'` {kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.filtermanager.md[`FilterManager`]

|`ui/index_patterns`
|`import { IndexPatternsService } from 'plugins/data/public'` {kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md[IndexPatternsService]

|`import 'ui/management'`
|`plugins.management.sections`. Management plugin `setup` contract.

|`import 'ui/registry/field_format_editors'`
|`plugins.indexPatternManagement.fieldFormatEditors` indexPatternManagement plugin `setup` contract.

|`ui/registry/field_formats`
|{kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldformats.md[`plugins.data.fieldFormats`]

|`ui/registry/feature_catalogue`
|`plugins.home.featureCatalogue.register`  home plugin `setup` contract

|`ui/registry/vis_types`
|`plugins.visualizations`

|`ui/vis`
|`plugins.visualizations`

|`ui/share`
|`plugins.share`. share plugin `start` contract. `showShareContextMenu` is now called
`toggleShareContextMenu`, `ShareContextMenuExtensionsRegistryProvider`
is now called `register`

|`ui/vis/vis_factory`
|`plugins.visualizations`

|`ui/vis/vis_filters`
|`plugins.visualizations.filters`

|`ui/utils/parse_es_interval`
|`import { search: { aggs: { parseEsInterval } } } from 'plugins/data/public'`. `parseEsInterval`, `ParsedInterval`, `InvalidEsCalendarIntervalError`,
`InvalidEsIntervalFormatError` items were moved to the `Data Plugin` as
a static code
|===

===== Server-side

====== Core services

In server code, `core` can be accessed from either `server.newPlatform`
or `kbnServer.newPlatform`:

[width="100%",cols="17, 83",options="header"]
|===
|Legacy Platform |{kib} Platform
|`server.config()`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.plugininitializercontext.config.md[`initializerContext.config.create()`]. Must also define schema. See <<config-migration>>

|`server.route`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.httpservicesetup.createrouter.md[`core.http.createRouter`]. See <<http-routes-migration, HTTP routes migration>>.

|`server.renderApp()`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.httpresourcesservicetoolkit.rendercoreapp.md[`response.renderCoreApp()`]. See <<render-html-migration, Render HTML migration>>.

|`server.renderAppWithDefaultConfig()`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.httpresourcesservicetoolkit.renderanonymouscoreapp.md[`response.renderAnonymousCoreApp()`]. See <<render-html-migration, Render HTML migration>>.

|`request.getBasePath()`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.httpservicesetup.basepath.md[`core.http.basePath.get`]

|`server.plugins.elasticsearch.getCluster('data')`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md[`context.core.elasticsearch.client`]

|`server.plugins.elasticsearch.getCluster('admin')`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md[`context.core.elasticsearch.client`]

|`server.plugins.elasticsearch.createCluster(...)`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.createclient.md[`core.elasticsearch.createClient`]

|`server.savedObjects.setScopedSavedObjectsClientFactory`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.setclientfactoryprovider.md[`core.savedObjects.setClientFactoryProvider`]

|`server.savedObjects.addScopedSavedObjectsClientWrapperFactory`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.addclientwrapper.md[`core.savedObjects.addClientWrapper`]

|`server.savedObjects.getSavedObjectsRepository`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md[`core.savedObjects.createInternalRepository`]
{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createscopedrepository.md[`core.savedObjects.createScopedRepository`]

|`server.savedObjects.getScopedSavedObjectsClient`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.getscopedclient.md[`core.savedObjects.getScopedClient`]

|`request.getSavedObjectsClient`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md[`context.core.savedObjects.client`]

|`request.getUiSettingsService`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md[`context.core.uiSettings.client`]

|`kibana.Plugin.deprecations`
|<<handle-plugin-configuration-deprecations, Handle plugin configuration deprecations>> and {kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.md[`PluginConfigDescriptor.deprecations`]. Deprecations from {kib} Platform are not applied to legacy configuration

|`kibana.Plugin.savedObjectSchemas`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]

|`kibana.Plugin.mappings`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]. Learn more in <<saved-objects-migration, SavedObjects migration>>.

|`kibana.Plugin.migrations`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]. Learn more in <<saved-objects-migration, SavedObjects migration>>.

|`kibana.Plugin.savedObjectsManagement`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]. Learn more in <<saved-objects-migration, SavedObjects migration>>.
|===

_See also:
{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.coresetup.md[Server’s
CoreSetup API Docs]_

====== Plugin services

[width="100%",cols="50%,50%",options="header",]
|===
|Legacy Platform |{kib} Platform
|`xpack_main.registerFeature`
|{kib-repo}blob/{branch}/x-pack/plugins/features/server/plugin.ts[`plugins.features.registerKibanaFeature`]

|`xpack_main.feature(pluginID).registerLicenseCheckResultsGenerator`
|{kib-repo}blob/{branch}/x-pack/plugins/licensing/README.md[`x-pack licensing plugin`]
|===

===== UI Exports

The legacy platform used a set of `uiExports` to inject modules from
one plugin into other plugins. This mechanism is not necessary for the
{kib} Platform because _all plugins are executed on the page at once_,
though only one application is rendered at a time.

This table shows where these uiExports have moved to in the {kib}
Platform.

[width="100%",cols="15%,85%",options="header"]
|===
|Legacy Platform |{kib} Platform
|`aliases`
|`N/A`.

|`app`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationsetup.register.md[`core.application.register`]

|`canvas`
|{kib-repo}blob/{branch}/x-pack/plugins/canvas/README.md[Canvas plugin API]

|`chromeNavControls`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md[`core.chrome.navControls.register{Left,Right}`]

|`docViews`
|{kib-repo}blob/{branch}/src/plugins/discover/public/[`discover.docViews.addDocView`]

|`embeddableActions`
|{kib-repo}blob/{branch}/src/plugins/embeddable/README.asciidoc[`embeddable plugin`]

|`embeddableFactories`
|{kib-repo}blob/{branch}/src/plugins/embeddable/README.asciidoc[`embeddable plugin`], {kib-repo}blob/{branch}/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.registerembeddablefactory.md[`embeddable.registerEmbeddableFactory`]

|`fieldFormatEditors`, `fieldFormats`
|{kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldformats.md[`data.fieldFormats`]

|`hacks`
|`N/A`. Just run the code in your plugin’s `start` method.

|`home`
|{kib-repo}blob/{branch}/src/plugins/embeddable/README.asciidoc[`home plugin`] {kib-repo}blob/{branch}/src/plugins/home/public/services/feature_catalogue[`home.featureCatalogue.register`]

|`indexManagement`
|{kib-repo}blob/{branch}/x-pack/plugins/index_management/README.md[`index management plugin`]

|`injectDefaultVars`
|`N/A`. Plugins will only be able to allow config values for the frontend. See<<configuration-service>>

|`inspectorViews`
|{kib-repo}blob/{branch}/src/plugins/inspector/README.md[`inspector plugin`]

|`interpreter`
|{kib-repo}blob/{branch}/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.md[`plugins.data.expressions`]

|`links`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationsetup.register.md[`core.application.register`]

|`managementSections`
|{kib-repo}blob/{branch}/src/plugins/management/README.md[`plugins.management.sections.register`]

|`mappings`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]

|`migrations`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]

|`navbarExtensions`
|`N/A`. Deprecated.

|`savedObjectSchemas`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]

|`savedObjectsManagement`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]

|`savedObjectTypes`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]

|`search`
|{kib-repo}blob/{branch}/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.search.md[`data.search`]

|`shareContextMenuExtensions`
|{kib-repo}blob/{branch}/src/plugins/share/README.md[`plugins.share`]

|`taskDefinitions`
|{kib-repo}blob/{branch}/x-pack/plugins/task_manager/README.md[`taskManager plugin`]

|`uiCapabilities`
|{kib-repo}blob/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationsetup.register.md[`core.application.register`]

|`uiSettingDefaults`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.uisettingsservicesetup.md[`core.uiSettings.register`]

|`validations`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md[`core.savedObjects.registerType`]

|`visEditorTypes`
|{kib-repo}blob/{branch}/src/plugins/visualizations[`visualizations plugin`]

|`visTypeEnhancers`
|{kib-repo}blob/{branch}/src/plugins/visualizations[`visualizations plugin`]

|`visTypes`
|{kib-repo}blob/{branch}/src/plugins/visualizations[`visualizations plugin`]

|`visualize`
|{kib-repo}blob/{branch}/src/plugins/visualize/README.md[`visualize plugin`]
|===

===== Plugin Spec

[width="100%",cols="22%,78%",options="header",]
|===
|Legacy Platform |{kib} Platform
|`id`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md[`manifest.id`]

|`require`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md[`manifest.requiredPlugins`]

|`version`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md[`manifest.version`]

|`kibanaVersion`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md[`manifest.kibanaVersion`]

|`configPrefix`
|{kib-repo}blob/{branch}/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md[`manifest.configPath`]

|`config`
|<<configuration-service>>

|`deprecations`
|<<configuration-service>>

|`uiExports`
|`N/A`. Use platform & plugin public contracts

|`publicDir`
|`N/A`. {kib} Platform serves static assets from `/public/assets` folder under `/plugins/{id}/assets/{path*}` URL.

|`preInit`, `init`, `postInit`
|`N/A`. Use {kib} Platform <<plugin-lifecycles,plugin-lifecycles>>
|===

=== See also

For examples on how to migrate from specific legacy APIs, see <<migrating-legacy-plugins-examples>>.
