How to run or call Custom code in extensions/server_connect/routes

I am following a guide over here https://youtu.be/c5OZZsVkOKY on how to integrate Salesforce OAuth 2.0 JWT Bearer Flow for Server-to-Server Integration here but I am not using Heroku, I am using my own server.

My question is, and I know I might missed the memo on how to do this, but what is the process to run custom code from extensions/server_connect/routes? below is a screenshot of the code.

I feel like I should know how to do this but I am having brain freeze.

I also have these two npm packages just like the guide (Salesforce and sf-jwt-token) much thanks to anyone you can help me translate it into Wappler way of writing custom code and run them

Zero help in these streets today?

@Teodor or @patrick what I am I doing wrong here. Should I have place this code in extensions/server_connect/modules instead? I am trying to run this Salesforce endpoint using jwt flow. Whats the best way to run this code?

To register a route handler you need to export a handler method.

exports.handler = (app) => {
  // your code here
  app.get('/myroute', async (req, res) => {
    res.json({data});
  });
};

Thanks for your reply @patrick I appreciate it I will modify as suggested. One more question at @patrick. How would I go about storing these, see image outline below as environment variable in Wappler?

turn above values like so below. Or what is your suggestion? Thanks again for your help I know its holidays.

You can store it in environment variables if you prefer that. In development you can set the environment variables in a .env file, we use the dotenv module for that (https://github.com/motdotla/dotenv). On your live server it depends on you host, you should not use the .env there.

Thanks for that I will try and put them in .env after. But I wanna walk through this exports.handler part first with you.

So I did your suggestion and I want you look and tell me if I am missing anything.



here is code version

const fs = require('fs')
const { getToken } = require('sf-jwt-token')
const privateKey = fs.readFileSync('private.pem').toString('utf8')

const conn = new jsforce.Connection();

exports.handler = (app) => {
    // your code here
    app.get('./testingpage2', async (req, res) => {
        try {
            const jwttokenresponse = await getToken({
                iss: '5GTJdfghhdfjdmcfdfhHFSGkadjsflc7789798fhjdfhjhGGGkfjdhf',
                sub: 'example@email.com',
                aud: 'https://login.salesforce.com',
                privateKey: '-----BEGIN RSA PRIVATE KEY-----NWEcdsFB4Z6/AutVCpdRWcA5XXSi/ oN1COYUCeqAiHuN41cfqSzc2mWcPxTvlcyqGAkL9aJrKcWMO3p4ErCelby3GoF5aiHa2j2zbZPinhwE4LLfqZ5rEynb + iHklT2qU5kVGV5AyfVz/0UXccSc+n3JFBzvYnTFEWgZel+xg2Ghdu2P7XctIutN2NGDvnMwIDAQABAoIBAHI/K7zhp0VEd7nWaf4XTF4QqIl3pCNGl5Odaw1KK75OTBZGghuDiORY270u+FjA7Wn9PFggRlO2O7efqQc6HHQJMAP/CcINBA9k8rlZfVBeFQUsiil3silnOg8uoUnxXT0yS+3jLmpJxMNGwzOKD/i2Q6P2LQv2elkeR6qZlX8LiglrbyrRGaEhii4gfyx9qDSW7EgBsNuvSJPaw5cOGmSKY0U7Y8kKP+gzpJvpkOtQhcs8kQhAX12ijofFZoBzadhVSUG1ncMl6XcGzRUBG2pj0LeQA6LPv7d8NNn5Hk7Yxb6piggIKmKJOy9SgZOhErLsywgwRa32r64GF1U30jECgYEA5SXMWCyPjGY5h5W4DCQH1ZozTHJ5lyxlMMi9hDOb55gNW+2+bLO5FuS8GKcsuHRJA0supwJJrHYyCwVp+3qUMvbpz51dL+FTTkd7p10gSTj38C06IYuFay/+aLvNpjZ4/15Yy----- END RSA PRIVATE KEY-----'
            });
            conn.initialize({
                instanceUrl: jwttokenresponse.instanceUrl,
                accessToken: jwttokenresponse.access_Token
            });
            const accounts = await conn.query("Select Id, Name From Account Limit 20");
            res.json(accounts);
        } catch (e) {
            console.log(e);
            res.json(JSON.stringify(e));
        }
    //added res.json({ data }); Wappler 
        res.json({ data });
    });
}; ```

Routes should start with a /. https://expressjs.com/en/starter/basic-routing.html

Remove res.json({ data }), that was only an example code.

const fs = require('fs')
const { getToken } = require('sf-jwt-token')
const privateKey = fs.readFileSync('private.pem').toString('utf8')

const conn = new jsforce.Connection();

exports.handler = (app) => {
    app.get('/testingpage2', async (req, res) => {
        try {
            const jwttokenresponse = await getToken({
                iss: '5GTJdfghhdfjdmcfdfhHFSGkadjsflc7789798fhjdfhjhGGGkfjdhf',
                sub: 'example@email.com',
                aud: 'https://login.salesforce.com',
                privateKey: '-----BEGIN RSA PRIVATE KEY-----NWEcdsFB4Z6/AutVCpdRWcA5XXSi/ oN1COYUCeqAiHuN41cfqSzc2mWcPxTvlcyqGAkL9aJrKcWMO3p4ErCelby3GoF5aiHa2j2zbZPinhwE4LLfqZ5rEynb + iHklT2qU5kVGV5AyfVz/0UXccSc+n3JFBzvYnTFEWgZel+xg2Ghdu2P7XctIutN2NGDvnMwIDAQABAoIBAHI/K7zhp0VEd7nWaf4XTF4QqIl3pCNGl5Odaw1KK75OTBZGghuDiORY270u+FjA7Wn9PFggRlO2O7efqQc6HHQJMAP/CcINBA9k8rlZfVBeFQUsiil3silnOg8uoUnxXT0yS+3jLmpJxMNGwzOKD/i2Q6P2LQv2elkeR6qZlX8LiglrbyrRGaEhii4gfyx9qDSW7EgBsNuvSJPaw5cOGmSKY0U7Y8kKP+gzpJvpkOtQhcs8kQhAX12ijofFZoBzadhVSUG1ncMl6XcGzRUBG2pj0LeQA6LPv7d8NNn5Hk7Yxb6piggIKmKJOy9SgZOhErLsywgwRa32r64GF1U30jECgYEA5SXMWCyPjGY5h5W4DCQH1ZozTHJ5lyxlMMi9hDOb55gNW+2+bLO5FuS8GKcsuHRJA0supwJJrHYyCwVp+3qUMvbpz51dL+FTTkd7p10gSTj38C06IYuFay/+aLvNpjZ4/15Yy----- END RSA PRIVATE KEY-----'
            });
            conn.initialize({
                instanceUrl: jwttokenresponse.instanceUrl,
                accessToken: jwttokenresponse.access_Token
            });
            const accounts = await conn.query("Select Id, Name From Account Limit 20");
            res.json(accounts);
        } catch (e) {
            console.log(e);
            res.json(JSON.stringify(e));
        }
    });
};

Thanks for that.

So I believe at this point I might out of league here because after I saved the file it broke all the pages. Its has been broking all the page even before I added your suggestion but I wasn’t sure if it was because of not using the exports.hander way.

Check the server logs if there are any errors, also enabling debug will output more logging that can help you in finding the problem.

dbug is on did some testing and it seem as if I comment out this line of code

const fs = require('fs')
const { getToken } = require('sf-jwt-token')
//const privateKey = fs.readFileSync('private.pem').toString('utf8')```

and put a ./ before the route path it work.

``` app.get('./testingpage2', async (req, res) => {
        try {```

Now here is the silly question. How do I get the data to display on the page or through Server Connect?

If the route works with ./ then use that.

You can use the api action for that. Or use server connect, it will not allow you to select the url, but you can set it in code view like <dmx-serverconnect id="serverconnect1" url="testingpage2"></dmx-serverconnect>.

Thanks for this I’ll try it now. @patrick I really appreciate you and your time.

I have honestly been struggling with this code for two weeks now until I finally decided to reach out here because I just couldn’t figure it out on my own.