Code review guidelines

Our code review process vets the app code for code quality, correctness, and security. This section lists a broad set of guidelines to be followed when developing apps.

App best practices

In order to deliver a rich user experience to customers, we recommend that you adhere to the following best practices adopted for:

Notifications

Use Interface methods in apps to provide notification of an operation’s status. Also, notification messages should be clear and concise.

Dos

  • Categorize notifications according to their types to make them meaningful (Success, Information, Warning, or Error).
  • Keep the notification messages simple and easy to understand.
  • Ensure that failure messages suggest an appropriate next step for users. For example: Retry at a later time, Contact the technical support team, or Refresh the page.

Don'ts

  • Avoid passing API error responses or the corresponding text in notification messages as they can be technical in nature and ambiguous.
  • Do not print javascript objects or stack traces in notifications.
  • Do not use console logs as an alternative to notifications.

Input validation

Poor input validation can break an app or introduce security vulnerabilities. For fields in a standard installation page, you can set validations in the iparams.json file. Also, appropriate validation checks must be included for custom app settings pages and forms that accept user inputs.

Dos

  • Validate values based on the field types. For example, it should not be possible to enter alphabetic characters in numeric fields.
  • If the validation fails, the app should provide clear and concise messages and suggestions on how to address the errors.
  • Provide helpful hints for complex form fields with appropriate example values.
  • Mark required fields clearly.

DO NOT use regex patterns randomly. Although their brevity adds value, an incorrect pattern could do more harm than good.

Lean apps and packaging

Remove unreachable code, unused variables, unwanted resources, and unused libraries to keep your app lean. Any source code that interacts with the Freshworks SDK must be packed within the app and submitted for review so that app users can tell what data from their account is used by the app. Business logic that uses this data can remain outside of the app package if required.

If a large part of the app source code is hosted outside the app, reviewers are likely to seek further information on the overall app architecture and how the business logic makes use of any personal information sourced by the app from a user’s account.

Dos

  • Modularize code to enable better code organization, readability, and extensibility. Modules separate functions of the application into highly organized and manageable pieces.
  • Use CDNs instead of locally packed libraries for code that does not use Freshworks platform APIs.
  • Remove unused npm modules from the code.
  • Ensure that the app uninstallation process undoes and cleans up the results of set-up actions, such as registering an external webhook.
  • Use the fdk pack command to pack the application after testing.

DO NOT access any code that makes use of the Freshworks platform APIs through CDN.

UI styling

Freshworks products are known for their intuitive and visually appealing user experience. As an extension of the products, apps should blend into the product visually and not stand-out.

Dos

  • Ensure that you adhere to the App UI guidelines.
  • Perform cross-browser testing to ensure uniformity in the UI.

Coding best practices

For you to develop maintainable and reliable apps, we recommend that you adhere to the following best practices adopted for:

Logging

Although console logs help debug code, avoid indiscriminate use of console logs.

Dos

  • Ensure that logs convey a meaningful message and proper context.
  • Make use of different log levels (Info, Debug, warn, and Error) to categorize logs. For example, exceptions should be logged with console.error() as shown in the image.
Correct console logCorrect console log

Don'ts

  • Do not log secure data such as keys, tokens, credentials, and so on.
  • Do not use console.log() extensively as it leads to clutter.
Incorrect console logIncorrect console log

Asynchronous control flows

Javascript uses an asynchronous I/O model where I/O operations (AJAX calls, database operations, file-system access, and so on) run independent of the main program flow and use an event loop to run call back functions after completion of the I/O operations. Also, treating an asynchronous control flow like a synchronous flow could lead to unexpected failures or bugs in the app.

The Freshworks platform APIs are asynchronous in nature and it is essential to sequence them appropriately.

Dos

  • Use promises to wrap asynchronous operations. Two or more asynchronous operations can be run back-to-back using promise chains. You can break the chain to obtain and process intermediate values.
  • Check the browser compatibility when using external promise libraries, such as bluebird and Q, or native promise methods such as promise.all().
  • Check the compatibility of modules with older environments when implementing complex control flows for asynchronous operations, such as the async module.
  • In async function declarations, always await the asynchronus callbacks before return.

Don'ts

  • Avoid callback hell.
  • Do not use setTimeout() to cope with asynchronous flows.
  • Do not access variables passed to or declared in the promise chain outside the promise.
  • Avoid global variables unless it is absolutely required.

Error handling

Errors in code must be appropriately handled based on the control flow (synchronous or asynchronous). Ensure that you test failure cases extensively.

Dos

  • Use the try..catch..finally block to handle synchronous errors.
  • Handle errors in asynchronous operations or promises with the same level of detail as for synchronous operations. You can use the err parameter in callbacks and the catch block in promises for error handling.
  • Ensure that the serverless component of the app returns a proper error response (for SMI apps and during App Setup Events) to the front end. This ensures business continuity in the face of unexpected errors and prevents negative experiences. DO NOT wrap everything inside a single try..catch block. Ensure that the code reacts appropriately to different exceptions.

Code minification and readability

Any code submitted as part of an app (with libraries included as assets) must not be in the minified or transpiled form. It has to be in a readable format to expedite code review and app certification processes.

Dos

  • Ensure that submitted code is readable (with consistent naming schemes and indentation and follows the DRY principle).
  • Although good code is self-documenting, use in-line documentation.
  • If you use React, Ember, Vue, or any other front-end framework, include the source files of your app in the src directory. The contents of the src directory are packed along with the app when the fdk pack command is run and can be submitted for review.

ES5 compliance

Use ES5 standards for client-side code as ES6 standards disrupt backward compatibility.

Security

The following security-related guidelines are mandatory for all apps. We recommend that you adhere to the following best practices adopted for:

Installation parameters

If your installation parameters contain sensitive customer data, ensure that you secure them.

Dos

  • Define iparams that store keys, credentials, or sensitive data as secure iparams.
  • In the front end, ensure that you access secure iparams only by reference, using templating as part of Request method calls, as shown in the following snippet.
Accessing secure iparams using request methodAccessing secure iparams using request method

Don'ts

  • Do not hardcode keys, credentials, or sensitive data in the app.
  • In the front end, do not use client.iparams.get() to fetch secure iparams. However, you can use client.iparams.get() to access non-secure iparams.

Request method

Apps depend on REST API calls, specifically when they are integrated with other products. Request method not only acts as a proxy to address CORS but also helps secure API calls. Using $.ajax calls instead of the platform Request method could lead to security vulnerabilities, especially when using secure iparams.

Dos

  • Take into account the pagination settings and rate limits when the app makes calls to the REST APIs.
  • Use the Request method’s templating feature to securely inject iparams in authorization headers (front end).
Iparams in authorization headersIparams in authorization headers
  • If an app works with an external custom web service (such as one hosted with a cloud provider), the web service must be authenticated for any access so that privileged information is secure and only accessible through the app.
  • Any external web services used must be capable of supporting considerable load and must have reliable uptime. Always prefer HTTPS over HTTP.

Don'ts

  • Do not hardcode keys, tokens, or credentials in REST API calls.
  • Avoid making HTTP requests as they are vulnerable to MITM attacks.

Code coverage

The code coverage summary lets you know the extent to which you have tested your app. For this, execute the fdk run command on the terminal. You can test your app for both positive and negative cases with equal importance.

Once you exit testing, the CLI prints the code coverage summary with which you can gauge how extensive your testing was. To access the latest code coverage report, navigate to the coverage folder from the app’s root directory.

Correct code coverageCorrect code coverage

Important:Each component in the coverage summary should be at least 80% for apps that are submitted to Freshworks Marketplace.

Incorrect code coverageIncorrect code coverage

To improve code coverage, you would need to test each and every functionality in your app for both success and failure cases, thereby detecting hidden bugs and improving the quality of the app.
The main components of the coverage summary are:

  1. Statement coverage: Checks if each statement in the code has been executed at least once.
  2. Branch coverage: Checks if each branch of each control structure has been executed. For example, in an IF statement, both the true and false branches need to be tested.
  3. Function coverage: Checks if each function (or subroutine) has been called in the code.
  4. Line coverage: Checks if each line of code has been executed (excluding comments/ conditionals). Note:Use the fdk pack command to pack the application after testing.

DO test positive and negative cases with equal importance.
DO NOT manually zip the app. Manual packing can corrupt or miss artifacts, pertaining to coverage metrics, in the .fdk directory and .report.json file.