diff --git a/packages/server-api/.eslintrc.js b/packages/server-api/.eslintrc.js index e6c897780..5a83ed227 100644 --- a/packages/server-api/.eslintrc.js +++ b/packages/server-api/.eslintrc.js @@ -19,7 +19,7 @@ module.exports = { 'prettier' ], parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint'] + plugins: ['@typescript-eslint', 'eslint-plugin-tsdoc'] } ] } diff --git a/packages/server-api/README.md b/packages/server-api/README.md new file mode 100644 index 000000000..402552a8b --- /dev/null +++ b/packages/server-api/README.md @@ -0,0 +1 @@ +Hello Tsdoc \ No newline at end of file diff --git a/packages/server-api/package.json b/packages/server-api/package.json index 62c01fbeb..a5edfb0ae 100644 --- a/packages/server-api/package.json +++ b/packages/server-api/package.json @@ -5,7 +5,9 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "build": "tsc --declaration", + "build": "npm run build:declaration && npm run build:tsdoc", + "build:declaration": "tsc --declaration", + "build:tsdoc": "typedoc --out docs --entryPoints src/index.ts --excludeNotDocumented", "watch": "tsc --declaration --watch", "prepublishOnly": "npm run build", "typedoc": "typedoc --out docs src", @@ -30,11 +32,12 @@ "chai": "^4.3.0", "eslint": "^8.34.0", "eslint-config-prettier": "^8.6.0", + "eslint-plugin-tsdoc": "^0.2.17", "express": "^4.10.4", "mocha": "^10.2.0", "prettier": "^2.8.4", "ts-node": "^10.9.1", - "typedoc": "^0.23.23", + "typedoc": "^0.23.28", "typescript": "^4.1.5" }, "peerDependencies": { diff --git a/packages/server-api/src/index.ts b/packages/server-api/src/index.ts index a73c08c04..c67e2b1ff 100644 --- a/packages/server-api/src/index.ts +++ b/packages/server-api/src/index.ts @@ -1,3 +1,5 @@ +import path from 'node:path' + import { IRouter } from 'express' import { PropertyValuesCallback } from './propertyvalues' @@ -47,13 +49,14 @@ export interface PropertyValuesEmitter { /** * This is the API that the server exposes in the app object that * is passed in Plugin "constructor" call. + * * * INCOMPLETE, work in progress. */ export interface PluginServerApp extends PropertyValuesEmitter, - ResourceProviderRegistry {} + ServerAPI {} /** * This is the API that a [server plugin](https://github.com/SignalK/signalk-server/blob/master/SERVERPLUGINS.md) must implement. @@ -74,23 +77,53 @@ export interface Plugin { name: string /** - * Called to start the plugin with latest saved configuration. Called + * Called to start the plugin with the latest saved configuration. Called * - for enabled (by configuration or by default) plugins during server startup - * - after stop() when the configuration of an enabled plugin has been updated - * in the admin UI + * - when the configuration of an enabled plugin has been updated + * in the admin UI. The server first stops the plugin and then restarts it + * with the new configuration * - when a plugin is Enabled in the admin UI + * @param configuration + * @param restart is a function that a plugin's code can call to set configuration + * to new values to restart the plugin */ - start: (config: object, restart: (newConfiguration: object) => void) => void + start: (configuration: object, restart: (newConfiguration: object) => void) => void /** * Called to stop the plugin. Called when the user disables the plugin in the admin UI. + * Also called when new configuration is saved from the Admin UI to first stop the + * plugin, followed by a `start` call. */ stop: () => void + + /** + * + * @returns A JSON Schema object or a function returning one. The schema describes + * the structure of the Plugin's configuration and is used to render the plugin configuration + * form in *Server => Plugin Config* + */ schema: () => object | object + + /** + * Optional additional configuration UI customisation + * + * @returns An object defining the attributes of the UI components displayed in the Plugin Config screen + */ uiSchema?: () => object | object + + /** + * Register additional HTTP routes handled by the plugin + * @param router Express Router object + * @returns + */ registerWithRouter?: (router: IRouter) => void signalKApiRoutes?: (router: IRouter) => IRouter enabledByDefault?: boolean + + /** + * A plugin can provide OpenApi documentation for http methods it exposes + * @returns OpenApi description of the plugin's http endpoints. + */ // eslint-disable-next-line @typescript-eslint/no-explicit-any getOpenApi?: () => any } @@ -113,9 +146,25 @@ export interface Metadata { description?: string } -export interface ServerAPI extends PluginServerApp { +/** + * These are the methods that a Plugin can use to interact with + * the server: get and produce data, log debug and error messages, + * report the plugin's status and handle plugin's configuration. + */ +export interface ServerAPI extends ResourceProviderRegistry { + /** + * Get the value by path for self vessel. + * @param path + * @returns + */ // eslint-disable-next-line @typescript-eslint/no-explicit-any getSelfPath: (path: string) => any + + /** + * + * @param path + * @returns + */ // eslint-disable-next-line @typescript-eslint/no-explicit-any getPath: (path: string) => any getMetadata: (path: string) => Metadata | undefined @@ -131,11 +180,54 @@ export interface ServerAPI extends PluginServerApp { //TSTODO convert queryRequest to ts // eslint-disable-next-line @typescript-eslint/no-explicit-any queryRequest: (requestId: string) => Promise + + /** + * Log an error + * @group Logging & Status Reporting + * @param msg + */ error: (msg: string) => void + + /** + * Log a diagnostic debug message. Ignored, unless plugin's debug logging + * is enabled in *Plugin Config*. + * @group Logging & Status Reporting + * @param msg + */ debug: (msg: string) => void - registerDeltaInputHandler: (handler: DeltaInputHandler) => void + + /** + * A plugin can report that it has handled output messages. This will + * update the output message rate and icon in the Dashboard. + * + * This is for traffic that the plugin is sending outside the server, + * for example network packets, http calls or messages sent to + * a broker. This should NOT be used for deltas that the plugin + * sends with handleMessage, they are reported as input from the + * server's perspective. + * @group Logging & Status Reporting + * + * @param count optional count of handled messages between the last + * call and this one. If omitted the call will count as one output + * message. + */ + reportOutputMessages: (count?: number) => void + + /** + * Set plugin status message (displayed in the Dashboard) + * @group Logging & Status Reporting + * @param msg + */ setPluginStatus: (msg: string) => void - setPluginError: (msg: string) => void + + /** + * Set plugin error message (displayed in the Dashboard) + * @group Logging & Status Reporting + * @param msg Pass undefined to erase a previously set error status + */ + setPluginError: (msg?: string) => void + + registerDeltaInputHandler: (handler: DeltaInputHandler) => void // eslint-disable-next-line @typescript-eslint/no-explicit-any handleMessage: (id: string, msg: any, skVersion?: SKVersion) => void savePluginOptions: ( @@ -172,27 +264,39 @@ export interface ServerAPI extends PluginServerApp { ) => void }) => void getSerialPorts: () => Promise + + /** + * Get information about the current course + * @group Course + */ getCourse: () => Promise + + /** + * Clear current destination + * @group Course + */ clearDestination: () => Promise + + /** + * Set destination + * @group Course + * @param destination PointDestination: either a waypoint with href to the + * waypoint resource or a position with longitude and latitude. + * @returns + */ setDestination: ( - dest: (PointDestination & { arrivalCircle?: number }) | null + destination: (PointDestination & { arrivalCircle?: number }) | null ) => Promise - activateRoute: (dest: RouteDestination | null) => Promise /** - * A plugin can report that it has handled output messages. This will - * update the output message rate and icon in the Dashboard. - * - * This is for traffic that the plugin is sending outside the server, - * for example network packets, http calls or messages sent to - * a broker. This should NOT be used for deltas that the plugin - * sends with handleMessage, they are reported as input from the - * server's perspective. - * - * @param count optional count of handled messages between the last - * call and this one. If omitted the call will count as one output - * message. + * Activate a route + * @group Course + * @param dest A route resource href with options to rever the route, + * set next point in the route and set arrival circle. + * @returns Promise that is fulfilled when the route has been successfully + * activated. */ - - reportOutputMessages: (count?: number) => void + activateRoute: (dest: RouteDestination | null) => Promise } + +export const SERVER_API_DOCS_PATH = path.resolve(__dirname, '../docs') \ No newline at end of file diff --git a/src/serverroutes.ts b/src/serverroutes.ts index c7689cf85..d2c6cbb2b 100644 --- a/src/serverroutes.ts +++ b/src/serverroutes.ts @@ -50,6 +50,7 @@ import { } from './security' import { listAllSerialPorts } from './serialports' import { StreamBundle } from './types' +import { SERVER_API_DOCS_PATH } from '@signalk/server-api' const readdir = util.promisify(fs.readdir) const debug = createDebug('signalk-server:serverroutes') // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -107,8 +108,8 @@ module.exports = function ( // mount before the main /admin mountSwaggerUi(app, '/doc/openapi') - // mount server-guide app.use('/documentation', express.static(__dirname + '/../docs/built')) + app.use('/server-api-docs', express.static(SERVER_API_DOCS_PATH)) app.get('/admin/', (req: Request, res: Response) => { fs.readFile(