Skip to content

Design Hub developer guide - storage plugins

Design Hub storage plugins automatically save compounds to external databases. 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

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

Storage plugins

This plugin type is intended to save important information from a design set, to a shared idea database.

Life-cycle

Design Hub scans the services directory to find all storage plugins and loads them on start.

storage plugin life cycle

Specification

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

An export plugin exports the following required properties:

Name Type Description
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.
initialize async function An initialization function that the plugin may use to signal to Design Hub that it needs to refresh its database contents. When signaled, Design Hub will start calling insert with batches of records.

Arguments: none
this includes domain

Return value:
Promise<true> if the plugin needs access to the entire Design Hub contents again.
Promise<false> if the plugin has up to date information.

Required: yes
insert async function Called when chemists create a compound with a batch of created compounds.

Arguments:
compound[] list of data structures containing chemical structure and metadata. See specification below.
this includes domain

Required: yes
update async function Called when chemists change the metadata of a compound with a batch of changed compounds. The function should have a void return type.

Arguments:
compound[] list of data structures containing chemical structure and metadata. See specification below.
this includes domain

Required: yes
domains array of strings List of domains where this plugin may be used. Use * to allow any domain. 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

Compound record specification

name type (max length) description example
project_key string (200) key of the project where this record belongs to 1
project_label string (200) label of the project where this record belongs to CXN-1
hypothesis_title string (500) label of the hypothesis attached to this record improve selectivity with ARG173
hypothesis_content_id string (60) internal identifier of the hypothesis 389dff34922bb2e689df6b93c191cf9e4ba67b64
designset_title string (500) label of the design set attached to this record route #1
designset_content_id string (60) internal identifier of the design set e346597dbd0951bc44cf90b04fe7455adcf35fc0
compound_id string (500) ID of the compound.
Deprecated
VXN00001
compound_virtual_id string (500) Virtual ID of the compound VXN00001
compound_substance_id string (500) Substance ID of the compound once obtained from registry. CXN001
compound_content_id string (60) internal identifier of the compound d94b689b6296a3175dabe0b0ff75675e1ae847c5
compound_structure string (16M) chemical structure of the compound in Marvin Document format <cml>...</cml>
compound_author string (500) user name of the compound author as obtained from the identity provider user@pharmatx.com
compound_create_date Date timestamp of the compound creation 2019-09-30T09:10:03.441Z
compound_modify_date Date timestamp of the last modification of the compound 2019-09-30T09:10:03.441Z
compound_deleted boolean flag of compound deletion true
compound_status string (100) human friendly label of the compound's status Ready for review
compound_priority string (100) human friendly label of the compound's priority Medium
compound_assignee string (500) user name of the current assignee of the compound, as obtained from the identity provider user@pharmatx.com
compound_fields Object JSON key-value pairs of Additional Fields. Fields are referred to by their name attribute. Optional. {"cst": "Isomer 1"}
compound_source_system string (255) label of the source of the compound. If configured by an import plugin, then the specified value, otherwise Design Hub AI
compound_source_id string (255) ID of the compound in the source system if imported, otherwise its value equals compound_virtual_id VXN0001
compound_tags array of strings the tags associated with the compound ["EXPEDITED_SYNTH", "IMPROVE_SOLUBILITY"]

Plugin skeleton

skeleton.storage.js

//@ts-check
"use strict";

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

/**
 * @typedef Compound
 * @prop {string} project_key
 * @prop {string} hypothesis_title
 * @prop {string} hypothesis_content_id
 * @prop {string} designset_title
 * @prop {string} designset_content_id
 * @prop {string} compound_virtual_id
 * @prop {string} compound_substance_id
 * @prop {string} compound_content_id
 * @prop {string} compound_structure
 * @prop {string} compound_author
 * @prop {Date} compound_create_date
 * @prop {Date} compound_modify_date
 * @prop {boolean} compound_deleted
 * @prop {string} compound_status
 * @prop {string} compound_priority
 * @prop {string} compound_assignee
 * @prop {Object} [compound_fields]
 * @prop {string} compound_source_system
 * @prop {string} compound_source_id
 * @prop {string[]} compound_tags
 * 
 * @typedef ConfigurationValues
 * @prop {{[key: string]: string}} secrets
 */


/**
 * determine if the database needs full resynchronization from Design Hub. Warning: this only runs on start and is extremely resource intensive
 * @returns {Promise<boolean>}
 */
async function initialize() {
  return false;
}

/**
 * Update values in database
 * @param {Compound[]} compounds
 * @returns {Promise<void>}
 */
async function updateCompounds(compounds) {
  for (const record of compounds) {
    //update compound
  }
}

/**
 * Insert values into database
 * @param {Compound[]} compounds
 */
async function insertCompounds(compounds) {
  for (const record of compounds) {
    //insert compound
  }
}

/**
 * Store and use values provided by Admin interface's Secret manager
 * @param {ConfigurationValues} config
 */
function onConfigurationChanged(config) {
  console.log("plugin-name configuration", config.secrets);
}

//export the necessary plugin properties
module.exports = {
  name: "skeleton-db",
  domains: ["*"],
  insert: insertCompounds,
  update: updateCompounds,
  initialize: initialize,
  onConfigurationChanged: onConfigurationChanged
};