# Calling a backend function in a configuration dialogue?

**URL:** <https://discourse.nodered.org/t/calling-a-backend-function-in-a-configuration-dialogue/82681>\
**Category:** Developing Nodes\
**Created:** [7 November 2023 12:02 UTC](https://discourse.nodered.org/t/calling-a-backend-function-in-a-configuration-dialogue/82681 "2023-11-07T12:02:11Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)\
**Post date:** [7 November 2023 12:02 UTC](https://discourse.nodered.org/t/calling-a-backend-function-in-a-configuration-dialogue/82681/1 "2023-11-07T12:02:11Z")

</div>

Scenario:  
NodeRED sits on a double network, can reach a backend and can be reached by the browser. The browser can't reach the backend directly.

A configuration node has two entries:

- baseURI (the URI the backend can be reached - not necessarily http(s)
- category: currently String

FIlling in the values and letting the node do its thing works like a charm. Now the challenge: each backend supports different categories and the "category" input should be replaced with a dropdown list showing the available categories. The backend has such a function.

The basic mechanic using a typeInput and reaching into the backend works:

```js
// Edit snipped
oneditprepare: function () {
      let apiList = getApiList(RED, $('#node-config-input-baseUrl').val());
      $('#node-config-input-api').typedInput(apiList);
    }
// calling backend
const getApiList = (RED, hostname) => {
  console.log(`Retrieve API List for ${hostname}`);
  let options = RED.settings.dominoConnectorApiList;
  return {
    types: [
      {
        value: 'apis',
        options: options
      }
    ]
  };
};

```

On the NodeRED side:

```js
const apiList = (baseURI) => {
  // HOW can I run this at setup time with the baseURI
  console.log('Running API List');

  // Hardcoded for now
  return [
    { value: 'basis', label: 'Basic CRUD' },
    { value: 'admin', label: 'Domino admin' },
    { value: 'pim', label: 'email, tasks, calendar (PIM)' },
    { value: 'poi', label: 'Office functions' },
    { value: 'setup', label: 'Setup REST' }
  ];
};

module.exports = function (RED) {
  function DominoConnectorNode(config) {
    RED.nodes.createNode(this, config);
    const node = this;
    node.baseUrl = config.baseUrl;
    node.api = config.api;
  }
  RED.nodes.registerType('domino-connector', DominoConnectorNode, {
    settings: {
      dominoConnectorApiList: {
        value: apiList(),
        exportable: true
      }
    }
  });
};

```

Or am I taking the wrong approach?

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [7 November 2023 12:40 UTC](https://discourse.nodered.org/t/calling-a-backend-function-in-a-configuration-dialogue/82681/2 "2023-11-07T12:40:56Z")

</div>

If you need the front end (i.e. the Nodes config HTML) to communicate with some backend.  
then you need to register an HTTP Admin Endpoint.

**Backend**

```auto
RED.httpAdmin.get('/some-unique-URI-endpoint',RED.auth.needsPermission('flows.read'),
		(request, response) => {
            const myObject = [
                { value: 'basis', label: 'Basic CRUD' },
                { value: 'admin', label: 'Domino admin' },
                { value: 'pim', label: 'email, tasks, calendar (PIM)' },
                { value: 'poi', label: 'Office functions' },
                { value: 'setup', label: 'Setup REST' }
              ]
			response.json(myObject)
		}
	);

```

**Front-End**

```auto
$.getJSON('some-unique-URI-endpoint', (data) => {
    $('#node-config-input-api').typedInput(data);
})

```

Ensure you use a unique endpoint identifier (as it can clash with other nodes if to vague)

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [7 November 2023 17:17 UTC](https://discourse.nodered.org/t/calling-a-backend-function-in-a-configuration-dialogue/82681/3 "2023-11-07T17:17:40Z")

</div>

> [@marcus-j-davies](#):
>
> If you need the front end (i.e. the Nodes config HTML) to communicate with some backend.  
> then you need to register an HTTP Admin Endpoint.

There is another option. But only for something that does not change until Node-RED (re)loads. The register function in the runtime allows passing of some data which can be read in the Editor.

As in this example:

```auto
    /** 2) Register the node by name. This must be called before overriding any of the
     * Node functions. */
    RED.nodes.registerType(uib.moduleName, nodeInstance, {
        credentials: {
            jwtSecret: { type: 'password' },
        },
        // Makes these available to the editor as RED.settings.uibuilderxxxxxx
        settings: {
            // The server's NODE_ENV environment var (e.g. PRODUCTION or DEVELOPMENT)
            uibuilderNodeEnv: { value: process.env.NODE_ENV, exportable: true },
            // Available templates and details
            uibuilderTemplates: { value: templateConf, exportable: true },
            // Custom server details
            uibuilderCustomServer: { value: (uib.customServer), exportable: true },
            // Current version of uibuilder
            uibuilderCurrentVersion: { value: (uib.version), exportable: true },
            // Should the editor tell the user that a redeploy is needed (based on uib versions)
            uibuilderRedeployNeeded: { value: uib.reDeployNeeded, exportable: true },
            // List of the deployed uib instances [{node_id: url}]
            uibuilderInstances: { value: uib.instances, exportable: true },
            // uibRoot
            uibuilderRootFolder: { value: uib.rootFolder, exportable: true },
        },
    })

```

The properties passed back have to start with the name of the node I believe.

In the example, the uibuilderInstances property is only correct at the time that Node-RED starts since it will change if someone, for example adds or removes a uibuilder node. So it is really a bit superfluous since I have to have an API anyway. I'll remove it one day. But the uibuilderCurrentVersion cannot change when node-red is running.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [7 November 2023 17:23 UTC](https://discourse.nodered.org/t/calling-a-backend-function-in-a-configuration-dialogue/82681/4 "2023-11-07T17:23:04Z")

</div>

Good to know, I thought `RED.settings` are only for the runtime - every day is a school day

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [7 November 2023 17:29 UTC](https://discourse.nodered.org/t/calling-a-backend-function-in-a-configuration-dialogue/82681/5 "2023-11-07T17:29:04Z")

</div>

> [@marcus-j-davies](#):
>
> I thought `RED.settings` are only for the runtime

Haha, they are - except when they're not. 😀

> [@marcus-j-davies](#):
>
> every day is a school day

How very true. And this has prompted me to improve some Editor related code where I turn on debug console output. Used to be if the node-red editor was accessed on localhost, it is now if the NODE\_ENV variable on the server was set to "dev" or "development". 🙂

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [7 November 2023 17:48 UTC](https://discourse.nodered.org/t/calling-a-backend-function-in-a-configuration-dialogue/82681/6 "2023-11-07T17:48:18Z")

</div>

> [@TotallyInformation](#):
>
> it is now if the NODE\_ENV variable on the server was set to "dev" or "development"

A little off-topic, but I apply the same approach in .NET, but with `clr` "preprocessor directives".

One of my projects in github (.NET), used to try and connect to a server on the host, if a debugger was attached - but had reports that when they use the lib while developing their app - it would timeout.

So, I added a 3rd profile `Debug - Local Server` that adds preprocessor directives, that is checked before trying to connect to a local server.

```sharp
#if DEBUG_LOCAL
   // connect to local sever
#endif

```

meaning they can still debug without connecting to a local server, by using the default `Debug` profile

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [21 November 2023 17:48 UTC](https://discourse.nodered.org/t/calling-a-backend-function-in-a-configuration-dialogue/82681/7 "2023-11-21T17:48:55Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
