# Resource Provider plugins

The Signal K server Resource API provides a common set operations for clients to interact with routes, waypoints, charts, etc but it does NOT provide the ability to persist or retrieve resources to / from storage.

This functionality needs to be provided by one or more server plugins that interface with the Resource API to facilitate the storage and retrieval of resource data.

These plugins are called Provider Plugins.

Resource API architecture:

This de-coupling of request handling and data storage provides the flexibility to persist resource data in a variety of different storage types as well as Internet based services.

Note

Signal K server comes with the resources-provider-plugin pre-installed which persists resource data to the local file system.

## Resources API

The Resources API handles all client requests received via the `/signalk/v2/api/resources` path, before passing on the request to registered provider plugin(s).

The Resources API performs the following operations when a request is received:

1. Checks for registered provider(s) for the resource type (i.e. route, waypoint, etc.)
2. Checks that the required ResourceProvider methods are defined for the requested operation (i.e. POST, PUT, GET, DELETE)
3. Performs an access control check
4. `POST` and `PUT` requests for Standard (Signal K defined) resource types are checked for validity of the submitted:
   - `resource id`
   - `resource data` against the OpenAPI definition.

Only after successful completion of all these operations is the request passed on to the registered provider plugin(s).

## Provider plugins

A resource provider plugin is a Signal K server plugin that implements the ResourceProvider interface which:

- Tells server the resource type(s) provided for by the plugin (i.e. route, waypoint, etc.)
- Registers the methods used to action requests passed from the server and perform the writing, retrieval and deletion of resources from storage. Note: The plugin MUST implement each method, even if that operation is NOT supported by the plugin!

Note

Multiple providers can be registered for a resource type (e.g. 2 x chart providers)

Note: The Resource Provider is responsible for implementing the methods and returning data in the required format!

## Registering as a Resource Provider

To register a plugin as a provider for one or more resource types with the SignalK server, it must call the server's `registerResourceProvider` function for each resource type being serviced during plugin startup.

Example: Plugin registering as a routes & waypoints provider.

    import { ResourceProvider } from '@signalk/server-api'

    module.exports = function (app) {

      const plugin = {
        id: 'mypluginid',
        name: 'My Resource Provider plugin'
      }

      const routesProvider: ResourceProvider = {
          type: 'routes',
          methods: {
            listResources: (params) => {
              fetchRoutes(params)
              ...
            },
            getResource: (id, property?) => {
              getRoute(id, property)
              ...
            },
            setResource: (id, value )=> {
              saveRoute(id, value)
              ...
            },
            deleteResource: (id) => {
              deleteRoute(id, value)
              ...
            }
          }
        }

      const waypointsProvider: ResourceProvider = {
          type: 'waypoints',
          methods: {
            listResources: (params) => {
              fetchWaypoints(params)
              ...
            },
            getResource: (id, property?) => {
              getWaypoint(id, property)
              ...
            },
            setResource: (id, value )=> {
              saveWaypoint(id, value)
              ...
            },
            deleteResource: (id) => {
              deleteWaypoint(id, value)
              ...
            }
          }
        }

      plugin.start = function(options) {
        ...
        try {
          app.registerResourceProvider(routesProvider)
          app.registerResourceProvider(waypointsProvider)
        }
        catch (error) {
          // handle error
        }
      }

      return plugin
    }

## Resource Provider Methods

A Resource Provider plugin must implement ALL methods in `ResourceProviderMethods` to service the requests passed from the server.

Each method should return a Promise on success and `throw` on error, if a request is not serviced or is not implemented.

Example:

    // SignalK server plugin
    module.exports = function (app) {

      const plugin = {
        id: 'mypluginid',
        name: 'My Resource Providerplugin',
        start: options => {
          ...
          app.registerResourceProvider({
            type: 'waypoints',
            methods: {
              listResources: (params) => {
                return new Promise( (resolve, reject) => {
                  ...
                  if (ok) {
                    resolve(resource_list)
                  } else {
                    reject( new Error('Error fetching resources!'))
                  }
                })
              },
              getResource: (id, property?) => {
                return new Promise( (resolve, reject) => {
                  ...
                  if (ok) {
                    resolve(resource_list)
                  } else {
                    reject( new Error('Error fetching resource with supplied id!'))
                  }
                })
              },
              setResource: (id, value )=> {
                throw( new Error('Not implemented!'))
              },
              deleteResource: (id) => {
                throw( new Error('Not implemented!'))
              }
            }
          })
        }

      }
    }