# Cannot call functions of config node

**URL:** https://discourse.nodered.org/t/cannot-call-functions-of-config-node/85929
**Category:** Developing Nodes
**Created:** [26 February 2024 13:52 UTC](https://discourse.nodered.org/t/cannot-call-functions-of-config-node/85929 "2024-02-26T13:52:38Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![hansimeister](https://avatars.discourse-cdn.com/v4/letter/h/a88e4f/32.png) [@hansimeister](https://discourse.nodered.org/u/hansimeister)
#### Post date: [26 February 2024 13:52 UTC](https://discourse.nodered.org/t/cannot-call-functions-of-config-node/85929/1 "2024-02-26T13:52:38Z")

</div>

Hi there!

I am trying to access a function namely getToken() defined in my config node in another node. However if I do it like the following:

```auto
var server = RED.nodes.node(node.server);
                console.log("server", server, "host", server.host);
                console.log("Server token ", server.getToken(server.host, server.username, server.password));

```

I get the error that this function is not defined. My server file looks like the following:

```auto
const fetch = require('node-fetch');
const WebSocket = require('ws');

module.exports = function (RED) {
  RED.nodes.registerType('sivideo-server', SiVideoServer, {});
  function SiVideoServer(config) {
    RED.nodes.createNode(this, config);
    const node = this;
    this.host = config.host;
    this.username = config.username;
    this.password = config.password;
    const Listeners = {};

    // Log the credentials for debugging purposes
    console.log('Credentials:', this.host, this.username, this.password);
    // Get the bearer token for websocket authentication
    if (this.host && this.username && this.password) {
      getToken(this.host, this.username, this.password)
        .then((token) => {
          node.context().set('token', token);
          // If token obtained, create websocket connection
          if (token && false) {
            node.ws = new WebSocket(`ws://${this.host}/api/ws/events/v1`, {
              headers: {
                Authorization: `Bearer ${token}`,
              },
            });

            console.log('Websocket connection created');
            // Register message event listener
            node.ws.on('message', (data) => {
              for (const [id, cb] of Object.entries(Listeners)) {
                cb(data);
              }
            });
          } else {
            console.log('No token obtained');
          }
        })
        .catch((error) => {
          console.error('Error fetching token:', error);
          throw error;
        });
    } else {
      console.log('No host, username, or password provided');
    }
  }

  // get the token from the server
  async function getToken(host, username, password) {
    try {
      const formData = new URLSearchParams();
      formData.append('grant_type', 'password');
      formData.append('client_id', 'GrantValidatorClient');
      formData.append('username', username);
      formData.append('password', password);

      console.log('Form Data:', formData.toString());
      const response = await fetch(`http://${host}/idp/connect/token`, {
        method: 'POST',
        headers: {
          'Content-type': 'application/x-www-form-urlencoded',
        },
        body: formData,
      });

      if (response.ok) {
        const data = await response.json();
        console.log('Token:', data.access_token);
        return data.access_token;
      } else {
        console.error('HTTP Error:', response.status);
        return null;
      }
    } catch (error) {
      console.error('Error fetching token:', error);
      throw error;
    }
  }

  // Register and deregister listeners
  function registerListener(NodeID, Callback) {
    console.log('Registering listener:', NodeID);
    Listeners[NodeID] = Callback;
  }

  function deRegisterListener(NodeID) {
    console.log('De-registering listener:', NodeID);
    delete Listeners[NodeID];
  }
};

```

---

<div class="post-metadata">

### Author: ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)
#### Post date: [26 February 2024 14:07 UTC](https://discourse.nodered.org/t/cannot-call-functions-of-config-node/85929/2 "2024-02-26T14:07:50Z")

</div>

Hi @hansimeister

Your `getToken` function is not attached to your config node in any way that would allow other nodes to access it - its just a function in the same file as your node.

You could add the following to your `SiVideoServer` function to expose the function on your node object:

```auto
this.getToken = getToken

```

---

<div class="post-metadata">

### Author: ![hansimeister](https://avatars.discourse-cdn.com/v4/letter/h/a88e4f/32.png) [@hansimeister](https://discourse.nodered.org/u/hansimeister)
#### Post date: [26 February 2024 14:40 UTC](https://discourse.nodered.org/t/cannot-call-functions-of-config-node/85929/3 "2024-02-26T14:40:52Z")

</div>

Tried it like below but unfortunately I still get the same error? @knolleary

```auto
module.exports = function (RED) {
  RED.nodes.registerType('sivideo-server', SiVideoServer, {});
  function SiVideoServer(config) {
    RED.nodes.createNode(this, config);
    const node = this;
    this.host = config.host;
    this.username = config.username;
    this.password = config.password;
    this.getToken = getToken;
    const Listeners = {};

```

---

<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: [26 February 2024 16:57 UTC](https://discourse.nodered.org/t/cannot-call-functions-of-config-node/85929/4 "2024-02-26T16:57:46Z")

</div>

I think it would help if you shared a slightly more complete view of the code.

Personally, I prefer to separate out the various functions so that the logic is a lot easier to follow. It tends to help you avoid these issues.

```javascript
let myconfig = {}

// This is run once when Node-RED Starts
module.exports = function myNode(RED) {
   // In case you want to reference RED in other functions
   myconfig.RED = RED

   // ... any setup functions here ...

   RED.nodes.registerType('myNode', nodeInstance)
})

// This is run once for each instance of the node in flows
function nodeInstance(config) {
   // if you need to reference red
   if ( !myconfig.RED ) return
   const RED = myconfig.RED
   
   // Initialise `this`
   RED.nodes.createNode(this, config)

   this.name = config.name
   this.topic = config.topic
   // ....

   this.getToken = getToken
   // Or, if you need to run it once for every instance:
   // this.token = getToken(host, username, password)

   // If you need to handle inbound msgs
   this.on('input', inputMsgHandler)

   // If you need to shut things down
   this.on('close', (removed, done) => {
      // ...
   }
}

// If needed (NB: Inherits `this` from `nodeInstance`)
inputMsgHandler(msg, send, done) {
   // if you need to reference red (quite likely in this fn)
   if ( !myconfig.RED ) return
   const RED = myconfig.RED

   // ...
}

async function getToken(host, username, password) {
   // ...
}

```

Then, if you want your getToken fn, you can simply add as another function at the end, reference `myconfig.RED` if you need to (which you indicate you don't here). And use it in any of the other functions as needed.

---

<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: [26 April 2024 16:57 UTC](https://discourse.nodered.org/t/cannot-call-functions-of-config-node/85929/5 "2024-04-26T16:57:57Z")

</div>

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