Command Line Deskera API Client in Node.js | Part 5: Show Me the Data!

Engineering Jul 13, 2020

This is Part 5 of the series of posts on writing a basic Command Line Deskera API client in Node.js.

Part 1 — Hello, World

Part 2 — Hello, You

Part 3 — Call an API Endpoint

Part 4 — OAuth 2.0 Authentication

Part 5 — Show Me the Data! (this post)

(Note: The GitHub links for this part are: Browse, Zip, Diff)

Get Logged-in User's Details

In the Part 4 — OAuth 2.0 Authentication, we successfully performed OAuth authentication with Deskera user's login. It is now time to show some details of the logged-in user from  deskera-token. To extract the user information, we will decode deskera-token as Base64 string.

Create a new file named user.js in src and add the following code in this file:

"use strict";

module.exports = () => {

  const getUserDetails = accessToken => {
    try {
      const tokenParts = accessToken.split(".");
      const userDetails = Buffer.from(tokenParts[1], 'base64').toString('ascii');
      return JSON.parse(userDetails);
    } catch ( err ) {
      console.log( "error obtaining user details from token", err );
      throw err;
    }
  };
  return {
    getUserDetails
  };
};

We have to call this function after obtaining token from authentication flow. Import the user module in bin/login.js.

const userClient = require( "../src/user" );

Call the getUserDetails function to extract user details from the token, and display the logged in user's information

const user = userClient();
const userDetails = user.getUserDetails ( token['deskera-token'] );
console.log( chalk.green.bold( "Successfully authenticated Deskera CLI application for " + userDetails.name + "!") );

Our bin/login.js should look like this with these changes

#!/usr/bin/env node

"use strict";

const chalk = require( "chalk" );
const dotenv = require( "dotenv" );
const authClient = require( "../src/auth" );
const userClient = require( "../src/user" );

dotenv.config();

const config = {
 deskeraAuthUrl: process.env.DESKERA_AUTH_URL,
 deskeraApiUrl: process.env.DESKERA_API_URL,
 clientId: process.env.DESKERA_CLIENT_ID,
 clientSecret: process.env.DESKERA_CLIENT_SECRET,
 scopes: process.env.DESKERA_SCOPES,
 redirectUrl: process.env.DESKERA_REDIRECT_URL
};

const main = async () => {
 try {
   const auth = authClient( config );
   const token = await auth.executeAuthFlow();

   const user = userClient();
   const userDetails = user.getUserDetails ( token['deskera-token'] );
   console.log( chalk.green.bold( "Successfully authenticated Deskera CLI application for " + userDetails.name + "!") );
 } catch ( err ) {
   console.log( chalk.red( err ) );
 }
};
main();

Update the CLI applications that are installed globally,

npm install -g .

and initial the login process

deskera-login

If all goes well, the console should display a success message with the logged-in user's name

 % deskera-login
Successfully authenticated Deskera CLI application for John Doe!

Get List of Invoices

We can now use  deskera-token  to call various Deskera APIs to obtain the required information. As an example, we will call the Invoice API to display the list of invoices for the logged-in user.

Create a new file named invoice.js in src and add the following code in this file:

"use strict";
const axios = require( "axios" );

module.exports = ( { deskeraApiUrl } ) => {
  if ( !deskeraApiUrl ) {
   throw new Error( "Deskera API URL is required." );
  }

  const getInvoices = async accessToken => {
    try {
      const config = {
        headers: { 
          "x-access-token": `${ accessToken }`
        }
      };
      const url = `${deskeraApiUrl}/v1/invoices/sales`;

      const res = await axios.get( url, config );
      return res.data;
    } catch ( err ) {
      console.log( "error getting invoices", err );
      throw err;
    }
  };
  return {
    getInvoices
  };
};

We have to call this function after obtaining token from authentication flow. Import the user module in bin/login.js.

const invoiceClient = require( "../src/invoice" );

Call the getInvoices function to get the invoices, and display it.

const invoice = invoiceClient( config );
const invoices = await invoice.getInvoices( token['deskera-token'] );
console.log( chalk.blue ("Invoices:") );
console.dir( invoices, { depth: 2 } ); //showing only 2 levels of data; set it to null to show all the levels

Our bin/login.js should look like this with these changes

#!/usr/bin/env node

"use strict";

const chalk = require( "chalk" );
const dotenv = require( "dotenv" );
const authClient = require( "../src/auth" );
const userClient = require( "../src/user" );
const invoiceClient = require( "../src/invoice" );

dotenv.config();

const config = {
 deskeraAuthUrl: process.env.DESKERA_AUTH_URL,
 deskeraApiUrl: process.env.DESKERA_API_URL,
 clientId: process.env.DESKERA_CLIENT_ID,
 clientSecret: process.env.DESKERA_CLIENT_SECRET,
 scopes: process.env.DESKERA_SCOPES,
 redirectUrl: process.env.DESKERA_REDIRECT_URL
};

const main = async () => {
 try {
   const auth = authClient( config );
   const token = await auth.executeAuthFlow();

   const user = userClient();
   const userDetails = user.getUserDetails ( token['deskera-token'] );
   console.log( chalk.green.bold( "Successfully authenticated Deskera CLI application for " + userDetails.name + "!") );

   const invoice = invoiceClient( config );
   const invoices = await invoice.getInvoices( token['deskera-token'] );
   console.log( chalk.blue ("Invoices:") );
   console.dir( invoices, { depth: 2 } ); //showing only 2 levels of data; set it to null to show all the levels
 } catch ( err ) {
   console.log( chalk.red( err ) );
 }
};
main();

Update the CLI applications that are installed globally,

npm install -g .

and initial the login process

deskera-login

The output:

 % deskera-login
Successfully authenticated Deskera CLI application for John Doe!
Invoices:
{
  content: [
    {
      openingInvoice: false,
      totalAmount: 11.52,
      totalAmountInBaseCurrency: 11.52,
      payableAccountCode: null,
      taxAmount: 0,
      openingDocumentNumber: null,
      warehouseCode: 'WH-0000001',
      dropShip: null,
...

In its colourful glory:

This concludes our five part series on writing a basic Command Line Deskera API client in Node.js. The full source code for this series  is available on Deskera's Github at https://github.com/Deskera/deskera-cli-node-sample.

Brajesh Sachan

Brajesh, drives direction of Deskera’s future technology and shapes Deskera as the technology leader. With his expertise and over 15 years of experience, he has significantly contributed to Deskera

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.