5 JavaScript Tricks

javascript software

Here's a quick video we put together to show you 5 JavaScript tricks that'll hopefully brighten up your coding day :)

Casey Li
CEO & Founder, BiteSite

Solution Types to Solve Small to Medium Sized Business Problems

business software

Many problems can be solved with software. Choosing the correct type of software to solve your problems can be tough, especially when you are trying to be price conscious and get the best bang for your buck.

This article will outline the benefits and negatives of some options a small to medium sized business has to solve the problems they encounter.

Non-Software Solutions

The first solution type is very broad, containing all non-software solutions. Forcing a solution by implementing software where it is not needed can cause more problems than the ones you are trying to solve.

This might be odd coming from a software developer but there are many problems that actually shouldn't be solved with software. These types of problems often need a short term solution and possibly are only complicated by the introduction of software where it is not needed.

The main advantage of a non-software solution is that it is probably what is currently implemented. There is no extra cost or effort involved in implementing this so if you only need a short term solution a non-software based solution is okay.

The problem with non-software solutions lies where choosing software is the correct option. It is easy to fall behind the competition if they are using software for the same type of problems. Software not only helps businesses stay ahead of the curve, it also makes it easier to store data safely, and easier to measure the success of the solution’s implementation.

Software Solutions

Benefits of a Digital Solution

The following three solutions - mass market, small scale mass market, and custom software - all contain the benefits of being a digital solution. Some of these benefits include the reliability and speed of access to data, the ability to automate tasks, and the ability to access the software from almost anywhere. Your problem might not need these exact features to solve the problem but they can be great selling points when changing to a software solution.

Mass Market Solutions

The mass market solutions category has the most customers due to the nature of its availability and breadth of features offered in its purchase. Mass market software is readily available software normally purchased on a subscription basis that can be used to help solve your problems. This type of software requires the purchase of many features under one fee and it is up to you to decide what you want to use.

Some pros to this type of software are that it is relatively inexpensive for what you obtain, it is immediately available directly after purchase, and it will have a large user base. The large user base means it likely will have good documentation, regular maintenance, and online help from other users with the same problems. The most attractive feature of this software is that it is ready to use “out of the box”. The problems you have can be solved almost instantly compared to the other solutions.

The cons of this type of software are related to the pros. The first one is that the cost includes many features that are not needed. This is reduced if the subscriptions are offered in a tier structure where you can choose the size of software available. In mass market software the same software is sold to many customers. It must be generalized enough that it will provide a solution to as many customers as possible so it can sell easier. This means that you will be paying for a product that will have many features not used. It is also hard to request changes to the software if it doesn’t fit your needs correctly. This is because it is not feasible for the company to apply all change requests to the software. Related to this is the lack of personal connection with any contacts at the company. Support tickets can be sent to the company’s general mailbox but it is tough to create a connection with anyone there that can be used in the future as a contact with the company.

Small Scale Mass Market Software

This category of software lies in the middle ground between mass market and custom software. Although it is in the middle of the two it rarely contains the best of both. This type of software is great if it fulfils your needs but can be hard to find.

This software can be used instantly just like mass market software as it has already been created. In terms of cost, it is cheaper than custom software but more expensive than mass market due to the lack of users to spread the development costs. The cost might be worth the product if it fits the needs of the purchaser. The lack of users also provides a higher chance for you to be heard by the company and have requests fulfilled via support tickets. This is where it comes close to custom software. If you submit a support ticket and it gets implemented, a developer would have changed the product to fit your needs. The difference from custom software here is that you can only suggest changes, not require them to be implemented.

Custom Software

The last solution category is custom software. This is software that has been designed specifically to meet the needs of the user and has the ability to be modified at any stage in its life. This software is exactly what the user needs and only what the user needs.

There are many advantages to choosing this type of software over the others but it will come at a cost.

All custom software will have a support team available who knows the product inside and out as they were the ones who created it. You can go directly to them to answer any questions or concerns. This is a benefit to them as well because over time your questions can help them understand what you need. They can then suggest improvements to the application that you might agree with but never thought about yourself.

The choice of features is where custom software really shines. It is the easiest out of all solutions to suggest changes since you own it. These changes are billed according to the work required but nothing is paid for that is not needed and discussed prior to its implementation. This allows you to improve your solution at any rate according to your budget.

You also have the most freedom to customize this solution to your problem. Related to customizing the solution to your needs is the ability to work with existing solutions. Custom software can be built to work with your existing environment and the technologies available. Due to this you have control over the security levels built into your solution. Buying premade software doesn't always allow the purchaser to choose how secure the software is.

As you can see custom software has many advantages but there are some points to consider when choosing this type of solution.

The first factor is the size of the solution required to fix the problem. If the software needs to be large to meet the requirements it can get very expensive. Another factor is how quickly the software is needed. Custom software is not ready to use immediately. There is an initial creation time before an MVP is available. This time until it is able to be used depends on the size of the MVP needed. The last point to consider is if you understand what the problem is you need fixed. Custom software shops are good at working with clients who are not 100% sure what they need but if you have no idea what the problem is there can be communication issues with what you need vs what is actually built.

Conclusion

Choosing the correct type of solution is the first step to solving the problem you have. This might not have told you exactly what you should go with but hopefully it gave you an idea of what avenue you want to pursue.

TL;DR: Solution Pros and Cons

(Photo by Sigmund on Unsplash)

Chris Francis
Software Developer, BiteSite

Why we don’t believe in fixed term contracts

business custom software software development

BiteSite was founded in the summer in 2012 and we’ve worked with a ton of clients on a lot of projects. With that comes a good amount of experience that has given us some confidence in saying what works for us and what doesn’t.

One thing in particular that we’ve experimented with in several different ways is the way we structure our contracts and after years of developing software, we’ve come to the conclusion that we don’t believe in fixed term contracts when it comes to software development.

What do we consider ‘fixed term’?

Alright, before we get started in explaining why we don’t believe in fixed term contracts, it’s probably a good idea to get on the same page as to what is a fixed term contract and what isn’t.

While there may be many different interpretations out there, for our purposes and for the purposes of this article, we consider a fixed term contract any contract that states something along the lines of:

You will get this output for this amount of money

Now, obviously contracts are not usually written this way, but they can be boiled down to something similar. What’s more common is something like this:

You will get Feature A, Feature B, Feature C, Feature D for $10,000.00

That is probably looking more like contracts that people are used to dealing with. Now obviously, contracts are usually more fleshed out than that, but the more detailed it gets, the more “fixed” we’re talking about, and as you’ll see, the more “fixed” a contract is the worse it is.

Now, there is a small but very important change we can make to these types of contracts that we are very much in favour of. This small change removes this “fixed” aspect of it. What’s the change? Simply removing either side of the equation:

You will get unknown for $10,000.00

Or

You will get Feature A, Feature B, Feature C for an unknown amount

In either of these cases, while you are fixing either the deliverables or the budget, you are NOT fixing both. When we talk about ‘fixed term’ contracts, we are talking about situations that fix both. If you allow either to be flexible, the contract does not fall into the ‘fixed term’ category.

Types of projects

BiteSite has an interesting history in that it didn’t used to be strictly a Custom Software development company. In the past, we focused on corporate video and before that we offered graphic design and photography services. As such, we want to be very clear about our philosophy around ‘fixed term’ contracts.

When we say we don’t believe in fixed term contracts, we are strictly talking about Custom Software projects.

While our philosophy might extend to other types of projects, we have a lot of concrete reasons and evidence around Custom Software projects and thus this article deals specifically with Custom Software projects.

Developing good software

Our belief around ‘fixed term’ contracts and why we avoid them really stems from our belief in how good software is developed - or rather what we believe is the best process to develop good software. We by no means invented any of these concepts but rather followed in the footsteps of great minds.

At BiteSite, we develop software following many Agile methodologies and principles. We use a process we’ve called Scrum Express (a slightly modified version of classic Scrum) and in our many years of experience, we find following these principles works really well.

Without going too deep into these principles, one of the biggest philosophies is continually integrating feedback into your development cycle. Whatever form the feedback takes, testimonials, usage statistics, data models - it’s important to take it in and incorporate it into your product on a continuous basis.

These principles are based on the notion that no one can really predict what users will do or how they will behave, and it’s important to put out software, observe, and iterate.

We’ve seen time and time again that these principles truly work in the real world. We’ll spend a little bit of effort developing a small feature that we’re excited about and find out very quickly that no one wanted to use it. So we stop developing it. On the other hand, we’ll add a small feature that we thought was a small fix and people loved it so we poured more resources into it.

It’s all well and good to read about these principles, but we (and I’m sure so many others) have seen it in action and it’s very powerful.

So how do you plan your software product? With this in mind, it may seem impossible to have a long term plan for a software product while maintaining effective development practices and in a way - it is.

If you subscribe to the philosophy described above, you should embrace the fact that you just don’t know what the future will bring.

Don’t get me wrong, it’s good to have a plan, and it’s good to have vision, and rough idea of where you’re going, but at the same time, you have to get used to the idea that within weeks if not days, your plan could completely change - that’s what agility is all about - the ability to change.

Processes and concepts like Scrum, Continuous Integration, MVP and more all account for this and give you powerful tools to take in feedback and remain agile.

If you think you can sit in a room full of researchers, designers, engineers and plan exactly how your software will work months from now without ever putting it in the users’ hands - then you’re adopting a waterfall approach - an approach that in our opinion is less effective.

It’s a pretty logical conclusion

If you believe in these agile philosophies as much as we do, then it’s a very logical conclusion as to why fixed term contracts are bad for software development.

Fixed term contracts lay out specifics about how a piece of software will look, behave, be architected, and more - all before some serious thought, but more importantly, all before it’s put into users’ hands.

If the contracts don’t leave room for flexibility or for the potential for the plan to be completely altered, then you could be developing software in a very ineffective way and basing your decisions on what’s written on a piece of paper rather than what your users are telling you.

By leaving your contracts open ended, you allow for the agile principles to shine through.

Is that it?

Following Agile development principles is definitely the main driving factor in our belief to avoid fixed term contracts, but we’ve also seen other benefits arise from it.

When you tell a developer to “Develop Feature A for $200.00”, they will constantly be racing against the clock. They’ll constantly be thinking of ways to shave off hours, and get the minimum amount done without taking some care. Not to mention, they’ll throw out any creative ideas, or spur of the moment inspiration to make things better. The distraction of needing to finish it in the exact time or amount or less leads to uninspired output.

Further to that, if the engineers, developers, or designers have any moral conscience, they’ll probably try to minimize the amount the customer spends. That’s great, but it can also stifle good conversations and discussions that can lead to great output.

When we moved to non-fixed term contracts, we felt we concentrated less on time, and more on just developing great software.

Can’t the contractors just buffer in the expense?

Whenever we’re faced with a client who just can’t do an open ended contract, we do what we believe most companies do - buffer the cost. So even if we think it’ll take 50 hours to produce, we’ll budget in 150 hours to cover these unforeseen costs.

While this can work, there are two reasons I’m not a fan of this approach. One, I think it’s an artificial and inaccurate way to account for the cost of what’s being done. It’s almost like saying “We can’t predict what’s going to happen, so we’re just going to charge you a bunch more money.” Secondly, if it really takes 50 hours, I never liked the idea of a company paying us more than what it took. If it took us less time, the client should pay us less.

Fixed budget is not fixed term

One thing I want to stress is a point I brought up when defining ‘fixed term’. If you remove either side of the equation, it removes the ‘fixed’ aspect of it.

So while we don’t believe in fixed term contracts, we are very much a fan of fixed budget contracts.

A fixed term contract may look like this:

We’ll develop Feature A, Feature B, Feature C for $10,000.00.

A fixed budget contract sounds more like this:

We’ll aim for Feature A, Feature B, and Feature C, however things could change and we may develop other features, but let’s keep our spending to only $10,000.00 maximum.

We find customers who are not comfortable with open ended contracts are at least more comfortable with fixed budget contracts.

Trust

This all sounds well and good, but I have to remind myself that I am writing from the perspective of the Custom Software service provider - not the client. I have to remind myself that it can be really scary to sign an open-ended contract with a provider. Sure I trust myself and my team, but how can I expect you, the client to, if you’ve never dealt with us or worked with us before.

The open-ended contracts we talk about are based big time on a trusting relationship between the vendor and the client.

So how do you establish this trust?

At BiteSite, we usually recommend starting with a small fixed budget contract - not fixed term - fixed budget. In fact, we’ve taken on starter contracts as small as $500.00 to start just to see how we work together.

I’ve never been a fan of companies who say, “We won’t talk to anybody who has a budget of less than $5000.00”. We’ll go as small as you’re comfortable with. Granted, we may not get much done for $100.00 or so, but if that’s what you want to spend, you’ll get to know us and then you’ll know whether or not to trust us with more.

Going through a pilot project of sorts is a great way to establish trust and if things go well, you can continue with that trusting relationship.

So how do we structure our contracts at BiteSite?

So with all that said, how do we structure our contracts at BiteSite? Well, it’s actually quite simple. If you strip away all the fine print, the only thing we really have in our contract is our hourly rates - no feature set, no deadlines - just our rate.

Once the contract is in place, the rest is discussed outside the contract. You only want to spend $1000.00 a month? No problem, we’ll keep track of that and not go over that. You want to try to get these 5 features in by March? No problem, we’ll aim to do that. Again - there is a trust factor, but this works really well for us.

If things go south, we find these contracts work really well too. Don’t like how we’re getting along or unhappy with the progress? Simply as us to stop, and we’ll stop.

One thing I should note, occasionally our contracts will include some extra details about feature sets that were discussed. However, these details in the contract are always stated as “rough plans” or “estimates” and emphasize that we are not bound to these plans.

Value based vs time based

Some of you out there reading this might be frustrated in our use of Time-based billing vs Value-based billing. Value based billing is definitely a philosophy with its merits, but frankly, I don’t know enough about it.

What I do know is it cost X dollars per hour per employee to run my company at a comfortable pace. That’s something concrete I can gravitate towards and something that’s easy for me to plan for. As such, for the time being I decide to use time-based billing.

It can be tough

It can be tough to sell the idea of open-ended contracts, but we find that once we explain our reasons, most clients get on board and it leads to a great working relationship.

I’m not saying that these types of contracts are for everybody, and I know there are definitely organizations that are bound by their contract processes that they have no other choice but to use fixed term contracts.

That being said, the more open ended contracts we put out there, the more evidence we get that it’s the right way to go. We hope that more and more organizations embrace this idea as we believe it lines up perfectly with how good software should be developed.

Footnote:

I want to give a special shoutout to ThoughtBot. ThoughtBot is a company that we look up to and admire greatly. ThoughtBot’s open source playbook was the first place I read about this idea and seeing them write about it publicly gave us the confidence to advocate for it in our daily work.

(photo by Cytonn Photography from Pexels)

Casey Li
CEO & Founder, BiteSite

Integrating Freshbooks API into an Expo App

expo freshbooks oauth react native software

So recently, I've been working on an Internal BiteSite staff application. Besides being useful to our team, it is also a testing ground for us to up our mobile development game.

One of the things we do at BiteSite is track our billable time using Freshbooks and to keep ourselves on track, we have weekly targets that we like to hit. It's not a strict thing - but a good way for us to gauge how we're doing.

With that, I wanted to create a feature in the app where we could easily see how close to our target we are. To achieve this, I had to integrate into the Freshbooks API. Although each piece wasn't too hard - there were a LOT of steps to take care of to make this work.

This article will outline all the steps I took to achieve this. This implementation is for an Expo App using Expo's AppAuth - but I'm sure this can easily be adapted for a bare React Native app using the regular React Native AppAuth.

Alright here we go.

TL;DR

If you just want to see the code, hit up the Gist here.

Before we begin

Before we begin, I want to mention that we will be using a library called expo-app-auth. Expo AppAuth is based on the React Native AppAuth library which itself is based on AppAuth libraries for iOS and Android. In this article, when we talk about AppAuth, we're talking about the Expo version - but a lot I'm sure applies to all of these libraries.

Pre-coding setup

So before you start coding your integration, you need to actually create a Freshbooks app. You can find the full instructions here, but basically, you login to your Freshbooks account and hit up the developer page. Once there you just create an app.

At that point, you should have Client ID and a Client Secret.

Before we move on, you should add one more thing. Click on 'Edit Application', and add a redirect URI. I used the value 'exp://127.0.0.1:19000/--/auth/redirect'. The URL will have to be a Deep Link (which you can generate using Linking.makeUrl.

Update: So to get the redirect URI to work with standalone apps, you have to do a little bit of manual URI generation. As of the writing of this article, Linking.markUrl will produce a triple slash URI. For example, if you set your scheme in your app.json to bitesite, and you call Linking.markUrl('/auth/redirect'), you'll end up with bitesite:///auth/redirect. So while the above exp:// URI will work when using the Expo Go app, it won't work when you deploy to a standalone app. So you'd think that all you have to do is add the bitesite:/// triple slash URL to the Freshbooks App. Unfortunately, Freshbooks doesn't consider this a valid URL at this point. As such, you'll have to manually code in the redirect URI to be only double-slash and then add bitesite://auth/redirect to the Freshbooks App. See the code below to see how I do it using app.json.

Ok, so your setup is complete - you'll have a Client ID, a Client Secret, and a Redirect URI.

Where to store your Client ID and Client Secret?

This is probably the most annoying part of this article if you're looking to implement something quick. Unfortunately doing something quick will ultimately be insecure.

Alright, so one of the issues with coding Expo apps is your effectively coding a Javascript bundle that can easily be exposed. As such, the authors of AppAuth recommend that you do NOT hard code your Client ID and Client secret into your Javascript. Sure you can test it out this way, but you shouldn't be storing in the code.

As such, we opted to store this in our own Rails app in the Database.

The Expo app that we're coding in this article will talk to 2 servers:

  1. The BiteSite web app
  2. Freshbooks

If you're cooding this for yourself, you will have to find your own way to store the Client ID and Secret (or at minimum the secret) somehwere that's not your code.

Our BiteSite web app's API only allows authorized users to then fetch the Client ID and Client Secret.

Building the Freshbooks API Client Object

When I started working on this, I really wanted to have a Javscript object that handled the complexity of authenticating against the Freshbooks API and making all the calls. When it comes down to it, this object can really be boiled down to a few basic functions

  • Authenticate the user against Freshbooks and store the resulting OAuth Token
  • Check if the user has an OAuth Token
  • Refresh the OAuth Token if necessary
  • Make Freshbooks API Calls using the OAuth Token

So let's create a basic object and add all the imports we'll need:

/* freshbooks_api_client.js */
import axios from 'axios';
import Constants from 'expo-constants';
import * as AppAuth from 'expo-app-auth';
import * as Linking from 'expo-linking';
import * as SecureStore from 'expo-secure-store';
import moment from 'moment';
import apiClient from './api_client';
import appSettings from '../../app.json';

const FRESHBOOKS_AUTH_KEY = 'freshbooks_auth';

const freshbooks_api_client = {
  /* We'll build our code here */
};

export default freshbooks_api_client;

Let's look at each of these in detail.

Log the user in to Freshbooks

So the very first step is we need to get the user to sign in. So to do this, we're going to use the expo-app-auth library which you can see is imported as AppAuth above.

Now, since a LOT of the code to get a new token and to refresh a token is very similar, I created an internal function. For lack of a better name, I called it internalAuthorize.

/* freshbooks_api_clients.js */
...

const FRESHBOOKS_AUTH_KEY = 'freshbooks_auth';

function internalAuthorize(refreshToken) {

  const internalAuthorizePromise = new Promise((resolve, reject) => {
    let authState;

    apiClient.get('/settings')
      .then(({ data: settings }) => {

        let freshbooksApiClientId;
        let freshbooksApiClientSecret;

        settings.forEach((setting) => {
          if(setting.name === 'freshbooks_api_client_id') {
            freshbooksApiClientId = setting.value;
          }

          if(setting.name === 'freshbooks_api_client_secret') {
            freshbooksApiClientSecret = setting.value;
          }
        });

        let redirectUri = Linking.makeUrl('/auth/redirect');

        if(Constants.appOwnership === 'standalone') {
          redirectUri = `${appSettings.expo.scheme}://auth/redirect`;
        }

        const config = {
          serviceConfiguration: {
            authorizationEndpoint: `https://auth.freshbooks.com/service/auth/oauth/authorize?response_type=code`,
            tokenEndpoint: 'https://api.freshbooks.com/auth/oauth/token'
          },
          redirectUrl: redirectUri,
          clientId: freshbooksApiClientId,
          clientSecret: freshbooksApiClientSecret,
          scopes: [],
        };

        if(refreshToken) {
          console.log("Attempt to refresh token...");
          return AppAuth.refreshAsync(config, refreshToken);
        } else {
          return AppAuth.authAsync(config);
        }
      })
      .then((returnedAuthState) => {
        authState = returnedAuthState;
        return SecureStore.setItemAsync(FRESHBOOKS_AUTH_KEY, JSON.stringify(authState));
      })
      .then(() => {
        resolve(authState);
      })
      .catch(() => {
        SecureStore.deleteItemAsync(FRESHBOOKS_AUTH_KEY).then(() => {
          resolve();
        });
      });
  });

  return internalAuthorizePromise;

}

const freshbooks_api_client = {
  ...
};

export default freshbooks_api_client;

This function returns a promise that basically resolves with an authState object if the authorization is successful and with nothing (undefined) if it's not successful.

The first 10 lines or so are just a get request to get the Client ID and Client Secret that is stored on the BiteSite app. apiClient is an axios api client for the BiteSite web app. So this is where your code will differ.

Once you have the Client ID and Client Secret though, you should be good to go.

Because Freshbooks doesn't use standard OAuth Provider data, we have to custom configure the AppAuth.authorize request. This is one of the keys that's hard to find in other places. Take note of the URL, the Client ID, the Client Secret, and the Redirect URI. Again the Redirect URI might not ultimately matter. Particularly the URL - do NOT use the Authentication URL from Freshbooks. AppAuth automatically constructs a URL using the values you pass into the config object so follow the code closely above.

With this configuration, you'll properly hit the Freshbooks Authentication URL.

What's great, is everything that follows is handled by the AppAuth library. All you have to do is call AppAuth.authAsync(config) and AppAuth will properly bring up a Browser window for the user to login into Freshbooks. If the user successfully logs in, the call to AppAuth.authAsync(config) returns a promise that resolves with the authState object which contains all the token information you need to make Freshbooks calls.

So once we have that, we simply store in using SecureStore.setItem.

Now that the token is stored, we are ready to use it to make Freshbooks API calls.

Now this internal function is used both in authorization and refreshing tokens. I just control this with a true/false parameter. So if we want to authorize, we just call internalAuthorize() and if we want to refresh, we call internalAuthorize(true).

To expose the authorization piece to the public, I wrap this call in a function:

/* freshbooks_api_clients.js */
...

function internalAuthorize(refresh) {
  ...
}

const freshbooks_api_client = {
  authorize: function() {

    const authorizePromise = new Promise((resolve, reject) => {

      internalAuthorize().then((authState) => {
        if(authState) {        
          resolve(true);
        } else {
          resolve(false);
        }
      });

    });

    return authorizePromise;
  },
};

export default freshbooks_api_client;

And with that, if somebody wants to authorize, they can just do this:

/* AnotherFile.js */
import freshbooks_api_client from '../path/to/freshbooks_api_client';

freshbooks_api_client.authorize().then((authorized) => {
  if(authorized) {
    console.log("Authorization succeeded!")
  } else {
    console.log("Something went wrong.");
  }
});

Check user's authorization state

Ok now that we logged the user in, throughout the rest of the app, it would probably be nice to check whether or not the user is 'logged into Freshbooks'. Really what that is is just checking whether or not we have a stored token.

What you should know is that the authState that came back when we authenticated is not just a string. It actually contains a lot of information including the token itself, its expiry date, etc. That's why when we originally stored it, we converted it (serialized it) into a string using JSON.stringify:

  ...
  return SecureStore.setItemAsync(FRESHBOOKS_AUTH_KEY, JSON.stringify(authState));
  ...

So if we want to check the if the user is logged in, and use the accessToken, it might be nice to have a little function that extracts out the serialized object, and deserializes it back into an object. So to do that, I created another internal function:

/* freshbooks_api_client.js */
...
function internalAuthorize(refresh) {
  ...
}

function getFreshbooksAuth() {
  const getFreshbooksAuthPromise = new Promise((resolve, reject) => {
    SecureStore.getItemAsync(FRESHBOOKS_AUTH_KEY)
    .then((data) => {
      if(data) {
        const freshbooksAuthObject = JSON.parse(data);
        resolve(freshbooksAuthObject);
      } else {
        reject('Could not find freshbooks auth object');
      }
    })
    .catch((error) => {
      reject(error);
    })
  });

  return getFreshbooksAuthPromise;
};

const freshbooks_api_client = {
  ...
};

export default freshbooks_api_client;

This internal function getFreshbooksAuth simply goes into our SecureStore, grabs the value, parses it into a Javascript object and returns a promise that resolves with the object.

The object that is resolved is basically the original authState object we got when we authenticated against Freshbooks.

Now we just need to this to the outside world. If the token exists, we're considered authorized.

/* freshbooks_api_client */
...
const freshbooks_api_client = {
  ...
  checkAuthorization: function() {
    const checkAuthorizationPromise = new Promise((resolve) => {
      getFreshbooksAuth()
      .then((freshbooksAuthObject) => {
        console.log("Freshbooks token active.");
        resolve(true);
      })
      .catch((error) => {
        resolve(false);
      });
    });

    return checkAuthorizationPromise;
  }
}

Refresh the token

Now that we have a way to check if we're authorized, we should be clear to make any API calls. Not exactly. Above, when I said "If the token exists, we're considered authorized" - that wasn't entirely true.

The think about OAuth tokens is that the expire - and actually - they expire pretty quickly. In some cases within 24 hours. Luckily, it's pretty easy to refresh the token.

So we need to modify our checkAuthorization slightly if we have a stored token but it's expired, we just need to refresh it.

/* freshbooks_api_client */
...
const freshbooks_api_client = {
  ...
  checkAuthorization: function() {
    const checkAuthorizationPromise = new Promise((resolve) => {
      getFreshbooksAuth()
      .then((freshbooksAuthObject) => {

        if(moment().isAfter(freshbooksAuthObject.accessTokenExpirationDate)) {

          internalAuthorize(freshbooksAuthObject.refreshToken).then((authState) => {
            if(authState) {
              console.log("Freshbooks Token refreshed.");
              resolve(true);
            } else {
              console.log("No Freshbooks Token found.");
              resolve(false);
            }
          });

        } else {
          console.log("Freshbooks token active.");
          resolve(true);
        }
      })
      .catch((error) => {
        resolve(false);
      });
    });

    return checkAuthorizationPromise;
  }
}

Notice that we're using our internalAuthorize that we coded before. Again - logging in and refreshing the token uses very similar code. Once the authState comes back from the refresh, we just store it the exact same way we stored the original authState.

So now, when we call checkAuthorization, if we're not logged in, we get a 'false' response, if we're logged in, we get a 'true' response, and if we need a refresh, the refresh happens and we get a 'true' response.

With this in place, any file can now easily check authorization status:

/* AnotherFile.js */
import freshbooks_api_client from '../path/to/freshbooks_api_client';

freshbooks_api_client.checkAuthorization().then((authorized) => {
  if(authorized) {
    console.log("Authorized!")
  } else {
    console.log("Something went wrong.");
  }
});

Make Freshbooks API Calls

Alright, now we're finally ready to make calls to the Freshbooks API. Making calls to the Freshbooks API is actually pretty simple - you just have to pass in a special string as the authorization header for your request.

The string looks like this:

"Bearer YOUR_OAUTH_API_TOKEN"

Since we have the API Token, this is actually pretty simple. Remember that we already have the internal getFreshbooksAuth function to grab the authState object. This object has a property called accessToken that we can use.

So we just set up an Axios instance with the proper header to make the API call. For those that are not familiar with Axios and use things like jQuery, think of Axios as another way to execute something like $.ajax.

So to put this together, I created a get function on our exported object:

/* freshbooks_api_client.js */
...

const freshbooks_api_client = {
  ...
  get: function(url) {

    const getPromise = new Promise((resolve, reject) => {
      getFreshbooksAuth()
      .then((freshbooksAuthObject) => {
        const internalFreshbooksApiClient = axios.create({
          baseURL: `https://api.freshbooks.com/`,
          headers: {
            'Accept': 'application/json',
            'Api-version': 'alpha',
            'Authorization': `Bearer ${freshbooksAuthObject.accessToken}`
          },
        });

        internalFreshbooksApiClient.get(url).then((response) => {
          resolve(response);
        })
        .catch(() => {
          reject();
        });
      });
    });

    return getPromise;


  }

With that final piece, we can now make calls from other files easily:

import freshbooks_api_client from '../path/to/freshbooks_api_client';

freshbooks_api_client.checkAuthorization().then((authorized) => {
  if(authorized) {

    freshbooks_api_client.get('/auth/api/v1/users/me').then((response) => {
      console.log(response.data.response);
    }
  } else {
    console.log("Something went wrong.");
  }
});

Conclusion

So with that, we now have a nicely encapsulated library with a pretty simple API:

freshbooks_api_client.checkAuthorization();
freshbooks_api_client.authorize();
freshbooks_api_client.get('/freshbooks/api/end_point');

I'm sure there is a lot of cleanup that can be done, but for now this is working and I'm pretty happy with it. Hope this helps others as well!

If you want to see the source code for our Mobile App, check it out here.

And as that will always be evolving, you can check out the Gist here.

Casey Li
CEO & Founder, BiteSite

Starting Small with Software

business software software development

You've seen all the success of large software companies such as Facebook, Amazon, Netflix, or anything else and thought, “I should do that”. So you come up with an idea and want to get started right away.

It goes without saying, investing in software is a safe bet for the future but jumping in without thinking is a sure way to overwhelm yourself. Your idea is great but let’s scale it back to a more manageable size. This allows you to not get overwhelmed with complexity and cost right away.

Approaching a company like BiteSite is a perfect way to ensure the project is the right size. At BiteSite we love to work with projects that start small and see where they end up.

What is a small project?

A small project to us is anything with a deadline of 1-3 months, and has a small set of concrete short term goals. At the end of the deadline the client will have a minimum viable product (MVP) that can be used by end users. This MVP will be able to be improved upon in the future once feedback is gathered.

Client

Starting small is advantageous to everyone involved, especially the client. Most of the advantages stem from not locking into a large project.

When a client decides to work with a custom software shop it is important that the company's culture works well with the client’s. This is mainly because the client is part of the development process. A small project does not lock a client into the company for a long period of time. This allows the client to feel out if they want to continue past the initial MVP.

Often in software development, the initial requirements do not turn out to be the final product. This is where it is dangerous to create large scale projects based off of fixed initial requirements. Short term contracts combat this by helping clients not lock into a product they end up not needing. Hence why we advocate for having a small set of concrete short term goals rather than immovable long term requirements. The short term goals can be added upon after users have tested the MVP and feedback is available as to what will be used.

Overall, the client will save time, effort, and money by choosing a small project and developing off of it in the future. The initial large scale idea will eventually be reached just in smaller increments.

BiteSite

Now you know why small projects are advantageous for customers, you might be wondering why BiteSite would ever advocate for a small project. As everyone knows, larger projects mean less uncertainty and more interesting work right?

Most of the time yes, but not always.

Larger projects are eventually what we try to work towards with all our clients but it’s rarely a good idea in software development to start with a large set of requirements and work towards a goal far in the future. Many requirements will not be known until the software evolves into something that can be tested by the end users.

The first reason to have smaller projects with new customers is to feel out what the end users will use. Small starting projects help us understand the clients and end users needs before anything large has been committed. This minimizes the time wasted creating software that is not needed. We can create an MVP to quickly see what features should be expanded upon and what ones will be dropped.

The next reason to start small is to show the client our competence and convince them their time, money, and effort spent on the project will be worth it. Diving into a large project doesn’t create trust as quick as a smaller project does since the finished product is so far in advance.

Larger projects having more interesting work is normally due to the complexity required. With custom software each project is unique so naturally it creates interesting work our developers possibly haven’t seen before. If the client continues the small project the complexity of the project will increase as well.

Hopefully you see how advantageous starting small can be.

Big projects can be intimidating but starting small will reduce the chance of being overwhelmed. The big idea is always there but chunking it off into smaller pieces is a better approach for everyone involved. There is nothing wrong with starting small. Afterall, Rome wasn’t built in a day.

(photo by Engin Akyurt from Pexels)

Chris Francis
Software Developer, BiteSite