async function inputMsgHandler(msg, send, done) { // eslint-disable-line no-unused-vars
    const RED = mod.RED

    // TODO: Accept cache-replay and cache-clear
    // Is this a uib control msg? If so, ignore it since this is connected to uib via event handler
    if ( msg.uibuilderCtrl ) {
        // this.warn('Received a uibuilder control msg, ignoring')
        done()
        return
    }

    // If msg has _ui property - is it from the client? If so, remove it.
    if (msg._ui && msg._ui.from && msg._ui.from === 'client') delete msg._ui

    // Get all of the typed input values (in parallel)
    await Promise.all([
        getSource('parent', this, msg, RED),
        getSource('elementId', this, msg, RED),
        getSource('heading', this, msg, RED),
        getSource('data', this, msg, RED), // contains core data
        getSource('position', this, msg, RED),
    ])

    // Save the last input msg for replay to new client connections, creates/update this._ui
    await elBuilder.buildUi(msg, this)

    // Emit the list (sends to the matching uibuilder instance) or fwd to output depending on settings
    emitMsg(msg, this)

    // We are done
    done()
}
3) Run whenever a node instance receives a new input msg
NOTE: `this` context is still the parent (nodeInstance).
See https://nodered.org/blog/2019/09/20/node-done
@param {object} msg The msg object received.
@param {Function} send Per msg send function, node-red v1+
@param {Function} done Per msg finish function, node-red v1+
@this {runtimeNode & uibElNode}