Not able to access Db from Iparams in Freshchat app

I was trying to access the Db from the iparams.js but I am getting the “Not found” error
in freshchat app however when I access it from the server.js I am able to access the Db

Hello @Chris_Blesson,

I am afraid that we cannot use DB capabilities inside the Custom Installation Page directly.

Custom Installation page supports following capabilites,

  1. Request API
  2. Server Method Invocation

You can use DB business logic, inside the SMI function.

Thank you @Saif Ill use Server Method Invocation.

Since I don’t know the use case that you are trying to solve, my suggestion can be little bit misleading which I want to put forward, before you take any action.

  1. If your are planning to save the inputs from the user before the app installation, and use them through out the app. Then I recommend you to use Installation Parameters and avoid using DB for this purpose.
  2. Database table is created only after the app is installed. For example, your DB business logic doesn’t actually do anything with SMI if your trying perform logic upon the installation. Reason: By that time, the NoSQL DB is not yet created.

However, my comment:

Is quite not clearly exposing these facts. Hopefully, I tried to make it clear.

If you still need help, do brief us a bit about the problem you are trying to solve; I can help you make better decision. :smile:

1 Like

Sure @Saif but SMI worked thank you.

1 Like

I tried it locally the SMI worked @Saif but installed it as a custom app the error again occurs.
So the scenario is Ill have a “save configs” button in the app installation this will be displayed after the app is installed. So in the app installation I will save the Webhook in the DB and next time Ill show the “save configs” button, when some configuration changes ill be fetching the Webhook from the Db and will make a api call to register the Webhook. But error occurs for SMI also.

Hi @Chris_Blesson,

Basically, the DB will return 404 before the app installation and if it was not saved before in the workflow. (If GET is called before SET for the same DB key)

For your use-case, the installation parameters can be used to get the webhook URL from the user and save it as an installation parameter via the postConfigs method. When the configuration changes, it can be obtained in the argument in the getConfigs method on the same settings page to fill the field to register the webhook.

Will this work for your use-case? Let me know if there are any challenges with this.

Hi @Raviraj the Webhook is Freshchat’s webhook it will be stored on AppInstall. In my scenario after the webhook is stored while visiting the settings page the second time or third time I will fetch the webhook from the Db and will register it in Third-party’s settings.

If it’s already stored, it will be possible to get it from DB in the further times when the configurations are changed in the settings page.

Could you share the code to make us understand where and when it is stored and where and when it is accessed? Please remove any sensitive information in the code while pasting it here.

  onAppInstallCallback: function() {
    generateTargetUrl()
        .then(function(url) {
            Wavecell.registerWebhook(url)
            renderData();
        })
        .fail(function(err) {
            console.error(err);
            renderData({ message: "Generating Webhook URL failed" });
        });
},

In this I will generate the webhook and will register

exports.registerWebhook = (url) => {
options = {....}
let registerWebhookUrl = "https://<%= iparam.WavecellDomain %>/config/v1/webhook"
$request.post(registerWebhookUrl, options).then(function(data) {
    freshchatUtil.storeInDb("url", url)

}, function(err) {
    console.error(err, "Error in regsitering webhook in wavecell")
})}

Storing in DB:

 exports.storeInDb = (key, val) => {
    $db.set(key, {
        val
    }).then(function(response) {
        console.info("Db Success", JSON.stringify(response))
    }, function(err) {
        console.error(err, "Error while storing in db")
    })
}

This all will take place in appInstall

Inside Server.js there is a function which is accessed by iparams to fetch the dataStore

fetchDataStore: async function(options) {

    console.info(options.key, "Inside smi")
    try {
        let dbData = await $db.get("url")
        renderData(null, { "response": dbData.val });
    } catch (err) {
        console.error(err)
        renderErrorMessage(err)
    }
}

Iparams.js:

 client.request.invoke('fetchDataStore', options).then(function(data) {
    let url = data.response.response
    let body = [{...}]
    let options = {
        headers: headers,
        body: JSON.stringify(body)
    }

    let registerWebhookUrl = "https://<%= iparam.WavecellDomain %>/config/v1/webhook"
    event.data.client.request.post(registerWebhookUrl, options).then(function(data) {
        console.info(data, "Webhook registered")
    }, function(err) {
        console.error(err, "Error in regsitering webhook in wavecell")
    })
}, function(err) {
    console.error(err)
})

This part will be used only after installation but still error in db occurs @Raviraj

@Chris_Blesson In the part where the data is stored in the DB, the function does not wait for the registerWebhook function to execute. So, the storeInDb function also may or may not complete.
To have a reliable operation and to make the installation fail, handle all the functions in the onAppInstallCallback method to wait for the execution to make sure it completes execution.

Regarding the iparams.js code, when is this executed and how are you sure that it will only happen after the installation?

Is this flow tested in the local environment or in the production environment as a custom app?

In Iparams I will hide the button that will fetch from Db the first time only if getConfigs is present I will show the button
In local it worked in custom app I got error.

Probably Ill check the OnAppInstallCallback part. @Raviraj

So, I’m guessing the DB key is not stored properly that results 404 in the subsequent calls whenever the settings are changed.

Could you check the function to handle the async functions to properly store it and to throw error upon failure?
Please confirm after testing with this change.

Sure @Raviraj Ill check and ill update soon

@Raviraj I checked it in the app ,I am getting success response for storing it in DB while onAppInstall and also for verifying I tried to fetch the webhook from onExternalEvent in the custom app and I am getting the webhook url stored from the Db.

@Chris_Blesson Thank you for the confirmation.

Sorry @Raviraj I think my previous reply was misleading it is getting stored in Db I am able to access it from Server.js but still the error occurs from Iparams.js

@Chris_Blesson Sorry for misunderstanding.

I have tested the same case as yours and I’m able to fetch the DB key from iparams after installation via SMI. It was stored in onAppInstall event handler method.

Could you share the latest source code from onAppInstall method and iparams after handling the db SET method async properly?

No issues @Raviraj I tried again today I am getting this error

 ReferenceError: $db is not defined at Object.fetchDataStore (server.js:8:26) at server.js:1:61 at server.js:1:200 at Script.runInContext (vm.js:133:20) at Request.Framework.sandboxExecutor (/opt/framework/framework.js:67:27) at Request.execute (/opt/framework/framework.js:149:10) at Request.execute (/opt/framework/framework.js:187:13) at Request.executeServerCode (/opt/framework/framework.js:165:12) at Object.exports.handler (/opt/framework/index.js:143:16) at Runtime.exports.handler (/var/task/index.js:6:8)

OnAppInstall Code:

onAppInstallCallback: function(payload) {
    generateTargetUrl()
        .then(function(url) {
            $db.set('url', { "val": url }).then(function(data) {
                console.info(data, "Db stored Successfully")
            }, function(err) {
                console.error(err)
            })
            Wavecell.registerWebhook(url, payload.iparams.subaccounts)
            renderData();
        })
        .fail(function(err) {
            console.error(err);
            renderData({ message: "Generating Webhook URL failed" });
        });
}

SMI Call from Iparams:

client.request.invoke('fetchDataStore', options).then(function(data) {
    console.info(data, "Db data from SMI")
}, function(err) {
    console.error(err)
})

SMI Code in server.js:

fetchDataStore: async function(options) {
    try {
        let dbData = await $db.get("url")
        console.info(dbData, "From Smi")
        renderData(null, { "response": dbData });
    } catch (err) {
        console.info(err)
        renderErrorMessage(err)
    }

}

Hi @Chris_Blesson,

We have found a bug in our end for this issue. It will be fixed soon.
I will update this thread when the fix is out.

1 Like