Skip to content

Design Hub developer guide - plugins

Design Hub's functionality can be extended by plugins in several workflows to meet the expectations for different user groups and use-cases. Plugins are generally implemented as NodeJS modules implementing a simple stateless API, connecting to one or more web services or databases.

Table of contents:

Plugin types

Realtime plugins

Realtime plugins encapsulate functionality that describe 1 virtual compound in 1 specific area of phys-chem properties, ADMET, commercial availability, literature data, in-silico assay data, structure checks or modeling.

For more information specifically related to realtime plugins, check the Developer guide - real time plugins.

Resolver plugins

A resolver plugin converts a corporate identifier into a chemical structure using a structure database lookup.

For more information specifically related to resolver plugins, check the Developer guide - resolver plugins.

Storage plugins

A storage plugin establishes and maintains a flat database of all virtual compounds in Design Hub. Typically implemented with a SQL database connection, this can be used to support advanced analysis, visualizations, or a backup.

For more information specifically related to storage plugins, check the Developer guide - storage plugins.

Registry plugins

A registry plugin helps lookup the synthesis status and substance ID of a compound by periodically executing searches in a compound registration system or ELN.

For more information specifically related to registry plugins, check the Developer guide - registry plugins.

Import plugins

Import plugins load chemical structures into Design Hub based on user input or automatically, followed by deduplication and processing of records.

For more information specifically related to import plugins, check the Developer guide - import plugins.

Company plugins

A company plugin assists authorizing a user by fetching project and group membership for the user.

For more information specifically related to company plugins, check the Developer guide - company plugins.

Configuration

All plugins are loaded automatically during startup of the application. The definition of plugins to load is set in the configuration guide. For more, check the Configuration guide's servicesDirectory section.

Development

For the successful development of a plugin, we recommend the following preparation:

  • 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

We recommend checking these basic introduction materials to get familiar with NodeJS

NodeJS beginner guide, Youtube (78m),
Getting started with NodeJS, Youtube (19m),
Intro to NodeJS, Youtube (48m)
NodeJS module description: https://nodejs.org/api/modules.html
Promise introduction: https://web.dev/articles/promises?hl=en

Plugin lifecycle

All plugin types support optional init and close lifecycle hooks. Design Hub calls these functions with a ServiceContext object as the parameter.

ServiceContext

Name Type Description
domain string The domain this plugin instance belongs to
dhUtils object Utility functions for chemical conversions, HTTP requests and more. See API of this.dhUtils
logger object Context-specific logger with debug, info, warn, error methods
schedule object node-schedule instance for scheduling recurring jobs

init(context)

Called once per domain on application startup, after the plugin is loaded. Use this to initialize connections, set up scheduled jobs, or prepare resources.

In a multi-domain setup, init is called separately for each domain with its own ServiceContext.

close(context)

Called once per domain on application shutdown. Use this to clean up resources, close connections, or cancel scheduled jobs.

Example

function init(context) {
  context.logger.info("plugin initialized");
  context.schedule.scheduleJob("0 */30 * * * *", async () => {
    // periodic task
  });
}

function close(context) {
  context.logger.info("plugin shutting down");
}

module.exports = {
  name: "my-plugin",
  init,
  close,
  // ... other exports
};

Utility functions

Most Design Hub plugins benefit from a library of commonly used functions. Design Hub provides these as a context object available via this.dhUtils inside every local plugin function call, including the following functions:

  • chemical file format conversion using JChem Microservices IO, used whenever a non-Chemaxon backend is involved in the plugin functionality
  • 2D rendering of chemical structures using JChem Microservices IO or Marvin Backend Image Generation Service, used whenever the (realtime) plugin needs to depict molecules
  • a general purpose HTTP library for REST/JSON, multipart or form-urlencoded requests, with basic or Bearer token authentication
  • a utility library for processing PDB files

No installation or configuration is required — this.dhUtils is automatically injected into the this context when Design Hub calls a local plugin. Remote plugins loaded from remoteServices do not receive dhUtils; use require only if you bundle your own copy of the utilities.

The @chemaxon/dh-utils npm package is deprecated. Plugins using require("@chemaxon/dh-utils") should migrate to this.dhUtils. See Migrating from @chemaxon/dh-utils below. The npm package will be removed in a future release.

Migrating from @chemaxon/dh-utils

Design Hub now injects utility functions into plugin callbacks. The following breaking changes apply when moving from the npm package to the built-in API.

How utilities are provided

Before (@chemaxon/dh-utils) After (built-in)
npm install @chemaxon/dh-utils and require("@chemaxon/dh-utils") No install — use this.dhUtils in plugin callbacks
Module imported at top of file Injected on this when Design Hub calls the plugin
Available everywhere in the plugin file Available in plugin callbacks and in init / close as context.dhUtils
Same for local and remote plugins Local plugins only — remote plugins (remoteServices) do not receive dhUtils

Breaking API changes

Area Before After
Context property dhutils (lowercase, when documented on this) dhUtils (camelCase) — this.dhUtils, context.dhUtils
PDB helpers dhutils.PDBUtilities.load(...) this.dhUtils.PDBUtilities.default.load(...) — datacollector plugins may also use this.pdbUtils.load(...)
findLigandsFromFile(pdbFile) async, on PDBUtilities findResidues(pdbFile) — synchronous
getCleanedImageURLs(...) separate method Removed — use getImageURLs(...); coordinate cleaning happens when the useMarvinNext feature flag is enabled
getImageURLs defaults width 400, height 260 width 500, height 400
getImageURLs parameters optional visualizationSettings argument Removed — use compoundVisualizationSettings in Configuration guide
batchConvert return type string[] { structure, successful, error? }[] — check successful per entry
append return type documented as array string — single merged multistructure file
convertFile return type Buffer string
req() default method GET POST
Service configuration JMS_IO_URL, JMS_STRUCTURE_MANIPULATION_URL env vars in docs Design Hub config keys: jmsIo / DH_JMS_IO, jmsStructureManipulation / DH_JMS_STRUCTURE_MANIPULATION, marvinBigService / DH_MARVIN_BIG_SERVICE — see Configuration guide

Migration steps

  1. Remove @chemaxon/dh-utils from package.json and delete the require / import at the top of the plugin.
  2. Replace dhutils.method(...) with this.dhUtils.method(...) inside plugin callbacks (calculate, resolve, runImport, etc.).
  3. In init / close, use context.dhUtils instead of a module-level import.
  4. Update PDB calls to use this.dhUtils.PDBUtilities.default.* (or this.pdbUtils.* in datacollector plugins).
  5. Rename findLigandsFromFile to findResidues and drop await if the call was only wrapped for the old async signature.
  6. Replace getCleanedImageURLs with getImageURLs and ensure useMarvinNext is enabled if cleaned coordinates are required.
  7. Update batchConvert callers to read .structure from each result object and handle successful === false.
  8. Remove any plugin-local .npmrc / Artifactory setup that existed only for @chemaxon/dh-utils.

Before and after

const dhutils = require("@chemaxon/dh-utils");

async function calculate(body) {
  const smiles = await dhutils.convert(body.compounds[0].mrvSource, "smiles");
  const images = await dhutils.getCleanedImageURLs([body.compounds[0].mrvSource]);
  const ligands = await dhutils.PDBUtilities.findLigandsFromFile(pdbContents);
  return { client: { smiles, images, ligands } };
}
async function calculate(body) {
  const smiles = await this.dhUtils.convert(body.compounds[0].mrvSource, "smiles");
  const images = await this.dhUtils.getImageURLs([body.compounds[0].mrvSource]);
  const ligands = this.dhUtils.PDBUtilities.default.findResidues(pdbContents);
  return { client: { smiles, images, ligands } };
}

function init(context) {
  context.dhUtils.get({ url: "https://example.com/health" });
}

Example usage

async function calculate(body) {
  const smiles = await this.dhUtils.convert(body.compounds[0].mrvSource, "smiles");
}

API of this.dhUtils

async get(data): String | Buffer | Object

Sends an HTTP GET request using the NodeJS fetch API. For parameters see below at async req.

Returns (a Promise of) the response body depending on encoding specified in the request.

async post(data): String | Buffer | Object

Sends an HTTP POST request using the NodeJS fetch API. For parameters see below at async req.

Returns (a Promise of) the response body depending on encoding specified in the request.

async req(data): String | Buffer | Object

Sends an HTTP request using the NodeJS fetch API. Parameters:

Name Type Required Description
url URL or string yes the HTTP URL to make the request to
jar CookieJar no See tough-cookie
formData FormData no See FormData Web API docs
isMultipartFormData boolean no When true, encodes formData fields as application/x-www-form-urlencoded instead of multipart
json boolean no Shorthand property to sending the body as stringified text with application/json headers and parsing the response as JSON as well
method string no POST (default), GET, PUT, PATCH, DELETE
headers Object no Key-value pair of request headers
body any no Body/payload of the request
followRedirect boolean no Follow redirects
timeout number no Number of milliseconds after which the request is aborted and an error is thrown
qs Object no Key-value pair of URL encoded query strings (search params) to append to the path of the URL. See URLSearchParams
auth Object no Allows Basic authentication using Base64 encoded credentials when username and password is specified. Allows sending Bearer tokens when bearer is specified
auth.username string no Username of basic authentication for base64 encoding
auth.password string no Password of basic authentication for base64 encoding
auth.bearer string no Value of bearer token

Returns (a Promise of) the response body depending on encoding specified in the request.

async convert(structure, toFormat): String

Converts the input chemical structure to the specified format using JChem Microservices IO.

Parameters:

  • structure (string): the chemical structure to convert
  • toFormat (string): the desired format string. See File Formats.

Note: use of this method requires JChem Microservices IO to be configured. See Configuration guide — set jmsIo / DH_JMS_IO / ML_JMS_IO, or use the jchemMicroServices gateway.

Returns:

  • the input chemical structure converted to the desired format.

async convertFile(fileContents, toFormat): string

Converts the input chemical structure file to the specified format using JChem Microservices IO.

Parameters:

  • fileContents (Buffer | String): the chemical structure file to convert
  • toFormat (string): the desired format string. See File Formats.

Note: use of this method requires JChem Microservices IO to be configured. See Configuration guide — set jmsIo / DH_JMS_IO / ML_JMS_IO, or use the jchemMicroServices gateway.

Returns:

  • the converted structure file contents as a string.

async batchConvert(structures, toFormat): { structure: string, successful: boolean, error?: string }[]

Converts the input chemical structures to the specified format using JChem Microservices IO.

Parameters:

  • structures (string[]): an array of chemical structures to convert
  • toFormat (string): the desired format string. See File Formats.

Note: use of this method requires JChem Microservices IO to be configured. See Configuration guide — set jmsIo / DH_JMS_IO / ML_JMS_IO, or use the jchemMicroServices gateway.

Returns:

  • an array of conversion results. Each entry contains the converted structure when successful is true, or an error message when conversion failed for that input.

async append(structures, toFormat): string

Merges multiple input chemical structures into a single multistructure file in the specified format using JChem Microservices IO.

Parameters:

  • structures (string[]): an array of chemical structures
  • toFormat (string): the desired format string. See File Formats.

Note: use of this method requires JChem Microservices IO to be configured. See Configuration guide — set jmsIo / DH_JMS_IO / ML_JMS_IO, or use the jchemMicroServices gateway.

Returns:

  • the merged multistructure file as a string.

async clean(structure, dimension, format): string

Rearranges the atomic coordinates of the input structure.

Parameters:

  • structure (string): the chemical structure to process
  • dimension (number): dimension to clean to. Values: 2, 3. Optional. Default: 2.
  • format (string): the desired format string. See File Formats. Optional. Default: mrv.

Note: use of this method requires JChem Microservices Structure Manipulation to be configured. See Configuration guide — set jmsStructureManipulation / DH_JMS_STRUCTURE_MANIPULATION / ML_JMS_STRUCURE_MANIPULATION, or use the jchemMicroServices gateway.

Returns:

  • the input chemical structure with new atomic coordinates in the desired format.

async getImageURLs(structures, width = 500, height = 400): string[]

Generates data URLs with base64 encoded PNG images of the input chemical structures. When the useMarvinNext feature flag is enabled, images are rendered via Marvin Backend Image Generation Service; otherwise JChem Microservices IO is used.

Parameters:

  • structures (string[]): an array of chemical structures to render as images
  • width (number): width of the image. Optional. Default: 500.
  • height (number): height of the image. Optional. Default: 400.

Visualization options are taken from the compoundVisualizationSettings application setting. See Configuration guide.

Note: use of this method requires JChem Microservices IO (jmsIo / DH_JMS_IO / ML_JMS_IO or jchemMicroServices) and, when useMarvinNext is enabled, Marvin Backend Image Generation Service (marvinBigService / DH_MARVIN_BIG_SERVICE).

Returns:

  • an array of data URLs with base64 encoded PNG images as strings. Failed conversions produce null entries. For more details see Data URLs.

createFormData(data): FormData

Creates a FormData instance from a key-value object of string fields.

appendFileToFormData(file, formData?): FormData

Appends a file entry to an existing or new FormData instance. The file argument is an object with value (string or Buffer) and options (filename, optional contentType).

PDB helpers

PDB file operations are available on this.dhUtils.PDBUtilities.default. Datacollector plugins may also use the same API via this.pdbUtils.

async PDBUtilities.default.load(pdbCode): string

Downloads a PDB file with the specified 4 letter code from the Protein Data Bank.

Parameters:

  • pdbCode (string): the 4 letter code of a PDB file

Returns:

  • the PDB file contents as a string

async PDBUtilities.default.findLigands(pdbCode): string[]

Downloads a PDB file with the specified 4 letter code from the Protein Data Bank and extracts the list of available ligands. Equivalent to calling load(pdbCode) followed by findResidues(pdb).

Parameters:

  • pdbCode (string): the 4 letter code of a PDB file

Returns:

  • the residue codes of the available ligands in the file as an array of strings.

PDBUtilities.default.findResidues(pdbFile): string[]

Extracts the list of available ligands from the specified PDB file. Replaces findLigandsFromFile from the deprecated @chemaxon/dh-utils npm package.

Parameters:

  • pdbFile (string): the contents of the PDB file

Returns:

  • the residue codes of the available ligands in the file as an array of strings.

async PDBUtilities.default.getResidue(pdbCode, ligandCode): string | false

Downloads a PDB file with the specified 4 letter code from the Protein Data Bank and extracts a specific ligand.

Parameters:

  • pdbCode (string): the 4 letter code of a PDB file
  • ligandCode (string): code of the ligand to extract, e.g.: HEM, A:HEM, or A:HEM350

Returns:

  • the ligand as a valid minimal PDB file, or false if the ligand was not found

PDBUtilities.default.getResidueFromFile(pdbFile, ligandCode): string | false

Extracts a specific ligand from the specified PDB file.

Parameters:

  • pdbFile (string): the contents of the PDB file
  • ligandCode (string): code of the ligand to extract, e.g.: HEM, A:HEM, or A:HEM350

Returns:

  • the ligand as a valid minimal PDB file, or false if the ligand was not found

History of changes

this.dhUtils (current)

  • utility functions are provided via this.dhUtils in local plugin callbacks and context.dhUtils in init / close. The @chemaxon/dh-utils npm package is deprecated — see Migrating from @chemaxon/dh-utils.

v5.0.3

  • getImageURLs uses Marvin Backend Image Generation Service for image rendering when the useMarvinNext feature flag is enabled

v4.2.18

  • with version 4 of dh-utils, the deprecated request dependency is replaced with the Node.js fetch API

v3.1.0

  • added append method

v3.0.1

  • package renamed from ml-utils to dh-utils

v2.5.0

  • added convertFile method

v2.4.0

  • added PDBUtilities.findLigandsFromFile method to the @chemaxon/dh-utils npm package (on this.dhUtils, use PDBUtilities.default.findResidues instead)

v2.2.2

  • added batchConvert method

v2.1.6

  • added clean method

v2.0.0

  • initial version with compatibility to JChem Microservices