Design Hub developer guide - resolver plugins

    Design Hub resolver plugins load molecules into the editor by fetching the source for a given corporate or database ID. These plugins are NodeJS modules, stored in a folder set by Design Hub's configuration file.

    Prerequisites

    • an instance of Design Hub available for development purposes, i.e.: the ability to stop and start it, to try different configuration options
    • familiarity with JavaScript, NodeJS and its module system
    • good understanding of Promises / async await

    {info} NodeJS introduction material: https://www.youtube.com/watch?v=_l96hPlqzcI (78m), https://www.youtube.com/watch?v=hKQr2DGJjUQ (19m), https://www.youtube.com/watch?v=cJVXP1bU68Y (48m) NodeJS module description: https://nodejs.org/api/modules.html Promise introduction: https://www.html5rocks.com/en/tutorials/es6/promises/#toc-async, https://github.com/kriskowal/q#readme

    Resolver plugins

    This plugin type is intended to fetch the MRV or SDF formatted chemical structure corresponding to a company specific ID or an alias, by making asynchronous network requests to RESTful JSON services.

    resolver plugin text input

    Life-cycle

    Design Hub scans the services directory to find the resolver plugins and generates a GUI element where chemists can type IDs. There may be only 1 resolver plugin active in a meeting room.

    resolver plugin life-cycle

    Specification

    Resolver plugins are NodeJS modules, denoted by their filename: *.resolve.js and their location in the services directory as configured during installation.

    A resolver plugin exports the following required properties:

    Name Type Description
    resolve async function The main function of the plugin, called when the chemist types an ID and hits enter. The function should resolve the given ID or alias to a chemical structure and must return a Promise of the results / be declared as an async function. The results are broadcasted by the application.

    Arguments:
    id (string) ID or alias
    this includes domain and roomName for the current call

    Return value: Promise The fulfillment value of the promise must be a chemical structure in SDF or MRV format. A rejected promise will display an error to the chemist.
    name string Unique identifier of the plugin, used by Design Hub for identification and internal communication. If multiple plugins use the same identifier, the last one to be loaded overrides the others.
    label string Human readable name of the plugin, used by Design Hub to display GUI elements related to this plugin.
    domains array of strings List of domains where this plugin may be used, when authentication is enabled in Design Hub. Use * to allow any domain. If no authentication is setup, this option has no effect. To query the configured domains, send a GET request to /domains or open /domains in your browser.
    onConfigurationChanged function A callback function that Design Hub calls during initialization and whenever an administrator updates the Secrets of the system.

    Arguments:
    config (Object) An object with secrets attribute containing the key-value pairs of secrets from the Admin interface

    Plugin skeleton

    skeleton.resolve.js

    //@ts-check
    "use strict";
    
    const dhutils = require("@chemaxon/dh-utils");
    
    /**
     *
     * @typedef ResolverContext
     * @prop {User} user
     *
     * @typedef User
     * @prop {string} userName
     * @prop {any} tokens OIDC TokenSet
     * 
     * @typedef ConfigurationValues
     * @prop {{[key: string]: string}} secrets
     */
    
    /**
     * @this {ResolverContext}
     * @param {string} id
     * @returns {Promise<string>}
     */
    async function resolve(id) {
        //find id in corporate database
    
        return "";
    }
    
    /**
     * Store and use values provided by Admin interface's Secret manager
     * @param {ConfigurationValues} config
     */
    function onConfigurationChanged(config) {
        console.log("plugin-name configuration", config.secrets);
    }
    
    module.exports = {
        name: "skeleton",
        label: "Skeleton IDs",
        resolve: resolve,
        onConfigurationChanged: onConfigurationChanged,
        domains: ["*"]
    };