Creating cron jobs in node.js: a real-life example using BambooHR

Do you have a requirement that you need to run some kind of process every X number of hours? Wondering on creating scheduled jobs in Node? If that’s why you are here, then this post will work for you.

This time, I’m going to write about node-cron. An NPM package used to schedule tasks that will execute in certain periods of time defined by cron expressions. Let’s start with some basics:

What’s a cron expression?

cron expression is a string containing some subexpressions that describe the details of the schedule that you want to create. Every subexpression is separated by a white space and have a limited amount of options to be set. The cron expression is defined from left to right, and it can contain from 5 to 7 subexpressions (fields from now on).

The library we selected, works with cron expressions from 5 to 6 fields and it works like this:

  • The first option is to set a scheduler with seconds. This field is optional and is only used when the cron expression has 6 fields. It accepts values from 0 to 59, or the wildcard ( * ).

  • The second option is used for minutes. It accepts values from 0 to 59, or the wildcard ( * ).

  • Third for hours. It accepts values from 0 to 23, or the wildcard ( * ).

  • Fourth for day of month. It accepts values from 1 to 31, or the wildcard ( * ).

  • Fifth for month. It accepts values from 1 to 12, the names of the months, or the wildcard ( * ).

  • Sixth and last for Day of week. It accepts values from 0 to 7, the name of each day, or the wildcard ( * ).

Besides the values accepted, each subexpression can have special operators that allows for more complex scenarios, for example:

  • Run every minute 10th and 20th minute: 10,20 * * * *

  • Run every 2 hours: * */2 * * *

  • Run every Sunday: * * * * Sunday

About node-cron

As mentioned before, we are using node-cron. An NPM package with more than 50,000 downloads weekly, and currently, as the time of this post, on version 2.0.3. In Github, it has 713 stars, 10 contributors and 20 releases since February 2016, which was the first release.

Since we are going to work in Typescript, I suggest also to install the types package for node-cron. You can install it by running:

npm install @types/node-cron —save-dev

Setting up node-cron

Creating a scheduled task with node-cron is a really easy task, and actually the basic examples from the documentation of the package explain it really well. Here is one of the examples from the page:

var cron = require('node-cron');
 cron.schedule('0 1 * * *', () => {
   console.log('Runing a job at 01:00 at America/Sao_Paulo timezone');
 }, {
   scheduled: true,
   timezone: "America/Sao_Paulo"

However, this example falls short if you work with a more real-life scenario; like retrieving information from a datasource, manipulate it and then insert it into another database. This is a typical case of a process that needs to be done when you are doing some kind of synchronization between two systems. And actually, today we are doing that same example.

Our use case will be to retrieve information from a system called BambooHR (used to manage employees of a company, salaries, vacations, etc), compare it with data from another system and then insert, update or delete the differences. So let’s start first with the cron job.

The cron job

We are going to create first a class that will contain all the logic of the tasks that will be run, for our case it will be called BambooCron. Here is the code for it:

import { schedule, ScheduleOptions, ScheduledTask } from 'node-cron';
import { parseExpression } from 'cron-parser';
import _ from 'lodash';
import moment from 'moment';
import { BambooService } from '../data-access/bamboo/bamboo.service';
import { UserService } from '../api/services/user.service';
import { TimeOffService } from '../api/services/timeOff.service';
import { IHumanResourceManagerService } from '../data-access/IHumanResourceManagerService';

export default class BambooCron {
    private options: ScheduleOptions = {
        scheduled: false
    private task: ScheduledTask;
    private bambooService: IHumanResourceManagerService;
    private usersService: UserService;
    private timeOffsService: TimeOffService;

    constructor() {
        this.task = schedule(process.env.CRON_EXPRESSION
            , this.executeCronJob
            , this.options);

    public startJob() {

    private executeCronJob = async () => {
        const format = 'YYYY-MM-DD hh:mm:ss';`Starting cron job at: ${moment().format(format)}`);

        this.usersService = new UserService();
        this.bambooService = new BambooService();
        this.timeOffsService = new TimeOffService();
        await this.processEmployees();
        await this.processTimeOff();

        const cronDate = parseExpression(process.env.CRON_EXPRESSION).next();`Finished cron job. Next iteration at: ${moment(cronDate.toDate()).format(format)}`);

    private async processEmployees() {
        const employees = await this.bambooService.getEmployees();
        const users = await this.usersService.getAllUser();
        const usersToAdd = _.differenceWith(employees, users, (employee, user) => {
            return === user.bambooId;
        const usersToDelete = _.differenceWith(users, employees, (user, employee) => {
            return === user.bambooId;
        usersToAdd.forEach(async (employee) => {
            await this.usersService.saveUser(employee);
        usersToDelete.forEach(async (user) => {
            await this.usersService.removeUser(user);

    private async processTimeOff() {
        const bambooTimeOffs = await this.bambooService.getTimeOffs();
        const dbTimeOffs = await this.timeOffsService.getAllFromProvider('bamboo');
        const users = await this.usersService.getAllUser();
        const timeOffsToAdd = _.differenceWith(bambooTimeOffs, dbTimeOffs, (bambooTimeOff, dbTimeOff) => {
            return === dbTimeOff.bambooId;
        const timeOffsToDelete = _.differenceWith(dbTimeOffs, bambooTimeOffs, (dbTimeOff, bambooTimeOff) => {
            return === dbTimeOff.bambooId;
        timeOffsToAdd.forEach(async (timeOff) => {
            const user = users.find(x => x.bambooId === timeOff.employeeId);
            if (user)
                await this.timeOffsService.saveTimeOff(timeOff, user.userNm);
        timeOffsToDelete.forEach(async (user) => {
            await this.timeOffsService.removeTimeOff(user);

Let’s explain this class by sections. First, the constructor is where the task is going to be scheduled. The method schedule, imported from node-cron, receives 3 parameters: the cron expression that is being retrieved from the environment file, then the callback to the job code and lastly, some options of the scheduler (in out case, the only option we set is that it won’t start immediately).

The method startJob is a simple one, since we specify that the job is not going to start as soon as we schedule it, we need to have a way to start it programmatically.

The following method is executeCronJob, here is where everything happens, at least from a high level. From here, we initialize all the services that we are using to retrieve or insert information and also we print some information messages to the console like the time the task is running and when will be the next time the job runs.

The next two methods are similar but works for different entities, so let’s explain the flow for each one. The first step is retrieve all the information needed by calling methods from the services instantiated in the executeCronJob method. Then, we compare the data using lodash’s differenceWith method (another famous package). And finally, from the arrays created, we either delete or add information to the database by calling the services again (no updates are being managed in this example).

A big design improvement

As I’m writing this post, I’m noticing that the methods processEmployees and processTimeOff are, in essence, the same thing. So they can be abstracted to another method that encompasses the implementations. Feel free to design it differently.

The bamboo service

Now, we are going to work with the service that retrieves information from bamboo.

import fetch from 'node-fetch';
import moment from 'moment';
import { IHumanResourceManagerService } from '../IHumanResourceManagerService';
import { Employee } from './employee';
import { VacationTimeOff } from './vacationTimeOff';

export class BambooService implements IHumanResourceManagerService {
    private bambooHeaders = {
        method: 'GET',
        headers: { 'Accept': 'application/json' }

    private getBaseUrl(endpoint) {
        const key = process.env.bambooKey;
        const baseEndpoint = '';
        const subdomain = process.env.bambooSubDomain;
        return `https://${key}${baseEndpoint}/${subdomain}/v1/${endpoint}`;

    public async getEmployees(): Promise<Employee[]> {
        const url: string = this.getBaseUrl('employees/directory');
        try {
            const response = await fetch(url, this.bambooHeaders);
            const directory = await response.json();
            return directory.employees
                .filter(employee => employee.workEmail)
                .map((employee) => {
                return {
                    id: parseInt(,
        } catch (error) {
            throw error;

    public async getTimeOffs(): Promise<VacationTimeOff[]> {
        const today = moment();
        const startDate = today.format('YYYY-MM-DD');
        const endDate = today.add(3, 'M').startOf('month').format('YYYY-MM-DD');
        const url: string = this.getBaseUrl('time_off/requests/?status=approved&start=${startDate}&end=${endDate}');
        try {
            const response = await fetch(url, this.bambooHeaders);
            const timesOff = await response.json();
            return => {
                return {
                    id: parseInt(,
                    employeeId: parseInt(timeOff.employeeId),
        } catch (error) {
            throw error;

Again, let’s review this by sections. First, we create some reusable headers and a getBaseUrl method. This method will create the URL that will be used to connect to Bamboo; this URL is created by reading some configurations from an environment file.

Then, we have two methods that get the information, one for the employees and another one for the time offs from Bamboo. Some logic is applied in here to limit the information retrieved, for example, for the time offs we just want to retrieve the requests created or updated for the upcoming 3 months, anything prior to that is not needed for our target system.

The database services

From the BambooCron class, we also use services that connects to our database. In our system, we are using typeorm (which I talked previously here), an ORM with mysql integration and supports typescript out-of-the-box. For this post, I’m just going to show the service to manage users, however all of them follow a similar approach, so you can extrapolate for the rest of the entities.

import { BaseService } from "./base.service";
import { Employee } from "../../data-access/bamboo/employee";
import { User } from "../../data-access/entity/user";

export class UserService extends BaseService{
  public getAllUser = async () =>{
    return this.dbContext.users.find({
      where: { statusTxt: 'active' }

  public async saveUser(employee: Employee): Promise<User> {
    let newUser = this.createUser(employee);
    try {
      await this.dbContext.users.insert(newUser);
      return newUser;
    } catch (error) {
      throw error;

  public async removeUser(user: User) {
    try {
      user.statusTxt = <any>{ statusTxt: 'inactive' };
    } catch (error) {
      throw error;

  private createUser(employee: Employee): User {
    const userNm = employee.workEmail.substring(0, employee.workEmail.indexOf('@'));
    const user: User = this.dbContext.users.create({
      email: employee.workEmail,
      fullNm: employee.displayName,
      userNm: userNm,
      statusTxt: <any>{ statusTxt: 'active' }
    return user;

The User service is pretty straight-forward. It has some CRUD operations like getting active users, saving new users and finally removing them (soft delete by changing the status). It extends a BaseService class which looks like this:

import { DbContext } from "../../data-access/dbcontext";

export class BaseService{
  protected dbContext:DbContext = new DbContext();

This one is even easier, since it only exposes a property that is called DbContext. This property is exposed to every service that inherits from it, and basically it grants the ability to use connections from typeorm to execute queries or transactions with the database. Finally, this is how the DbContext class looks like:

import { Connection, createConnection, EntityManager, Repository } from "typeorm";
import { User } from "./entity/user";

export class DbContext {
    private connection: Connection;
    constructor (){

    private async init(){
        try {
            this.connection = await createConnection({
                "name": `connection-${new Date().getTime()}`,
                "type": "mysql",
                "host": ANY_HOST_HERE,
                "port": 3306,
                "username": ANY_USERNAME_HERE,
                "password": ANY_PASSWORD_HERE,
                "database": ANY_DATABASE_HERE,
                "synchronize": false,
                "logging": true,
                "entities": [
        } catch (error) {
            throw error;
    public get manager() : EntityManager {
        return this.connection.manager;

    public get users(): Repository<User>{
        return this.manager.getRepository(User);

The DbContext class is a reduced version of the one I use, it has more entities but the rest of the design is the same. First, we have an init method that creates a connection every time the DbContext is instantiated, and this connection receives all the entities and database information needed to create it.

And then, for every entity, we expose a getter property that expose the repository for each one of the entities that the typeorm will map to.

Finally, where do we execute all of this code. Since it needs to be executed or started as soon as the Node service starts, we add the code to the index.ts file of express.js, like this:


const cron = new BambooCron();

const port = parseInt(process.env.PORT);
export default new Server()


Finally, we have arrived to the end, and if you are here also, it means that you have created all the necessary code to run a scheduled task using node-cron and typeorm. Now, this is just one of the many use cases that can be covered with this design, so please adapt it as best as you see fit to whatever case you have to solve.

If you have any comment, don't hesitate in contacting me or leaving a comment below. And remember to follow me on twitter to get updated on every new post.

Companies Agility: A report by Scrum Alliance

A couple of days ago, the Scrum Alliance published a report called “The Elusive Agile Enterprise: How the Right Leadership Mindset, Workforce and Culture Can Transform Your Organization”.

In this report, Scrum Alliance and Forbes surveyed more than 1,000 executives to determine how important is the agility in an organization, its degree of success in transformation efforts and how much progress the companies have implementing this type of frameworks. Among all the respondents, there were 10% that are from Latin America (I’m from Costa Rica), so, I would have liked to read the results from this area, but the overall results are equally interesting. Also, those executives weren’t only from a technology oriented company, but also from other areas, however, I would like to comment on some aspects of the report from an IT perspective.

Geography distribution

Personal creation based on report data

One key thing to notice is that they want to measure the agility of a company, not the agile framework they are using (still, there is a 77% of these companies that leverage Scrum as their main framework). But, what is agility and what is being agile? agility is the property of an organization to respond to market changes and still deliver value to the customers, whereas agile is an organizational approach and mindset defined by the values and principles detailed in the Agile Manifesto.

Based on this premise, the report defines several benefits that are obtained after achieving a high level of agility within the company, such as:

  1. Faster time to market:

  2. Faster innovation

  3. Improved financial results

  4. Improved employee morale

Organizational changes

To achieve the mentioned benefits, the respondents affirmed that there were several changes that needed to be applied in order to redefine the company’s processes and reflect the agile mindset. In the report, Scrum Alliance mentioned the top 7 changes, but in order to not spoil the article, I would like to comment some of them with experiences that I’ve seen first-hand to be applied, and succeed.

  • Introduce an agile mindset

Being agile is not only about using Scrum (or any other flavor), perform some of the ceremonies or events that are required, and deliver software. The processes definitely are important, but the people are equally, or more important.

Having an upper management that believes in agile methodologies and promote them, facilitates the transition heavily. Implementing a change from the bottom-up, is nearly impossible, but when it comes from the higher grounds, it’s a quick, fluid and flexible process.

I worked for one organization that had Scrum implemented partially, but not the agile mindset. They performed some of the ceremonies when possible, defined their sprints to have incremental products, but in the other hand, had a requirements process that resembled a lot to the waterfall scheme and the releases were done until the end of the development. The development process was really flexible, and we were able to adapt to some changes, but still there were some gears that didn’t feel right.

The main problem was that the customers weren’t involved with the development process at all, and they were expecting that we exceeded their expectations. This wasn’t going to work, and in fact, it didn’t!

To remediate this, we tried to create backlogs that allowed customers to give their inputs and define what needed to be done. It worked in some things, but still there wasn’t much involvement from the customers, even though that we invited them. At this point, there wasn’t a single point of authority, someone that could work as the Product Owner (something fundamental), so we had to facilitate its creation.

To do this, we talked with the managers of each area that were part of the application and explained them what changes were needed and the possible benefits. They trusted us, and a new group was formed that worked as the Product Owner; this group consisted on a representative of each area, and even though this is not the regular Scrum process, it worked much better and we got much more feedback than before.

The agile mindset was introduced, little by little, to obtain success.

  • Create incentives that promote agility

In another organization, the agile mindset was much better. Some processes were already defined there, customers agreed with the methodology and got involved in it, the ceremonies were executed and the benefits were visible. Even so, this organization needed some optimization because the processes weren’t applied uniformly across all development teams.

To solve this, a group of people from the organization decided to create a group to lead all the Agile efforts, and the first big task was to standardize the process across every team. Among many options, the one who won was to create a contest, but not a simple one.

The contest consisted in having all teams follow the process of the organization and the Scrum best practices. There were 4 phases and for every phase, a common goal. Each team earned points depending on how good the practices and the process were followed. For example: for the first phase the DSUs were the main goal, and a team earned one point for every DSU done in less than 10 minutes, using the parking lot technique granted extra points. For the second phase, backlog grooming, sprint planning and sprint retrospective events were evaluated. The next phases evaluated customer involvement and product deliveries.

At the end of the contest, a winner was selected from all teams and some prizes were given, but the real outcome was that all the teams managed to follow the same process and practices.

  • Train workforce

As I mentioned before, people are the most important factor when there are changes in any organization. People will determine how quick the change is applied, but there will always be blockers that are needed to be managed, for example: resistance to change, lack of communication, ignorance.

In my opinion, training people to work with Scrum is mandatory, and there are really clever activities that embodies the agile mindset, demonstrates how Scrum is supposed to work and make people enjoy the time spent learning about it. For example, I’ve been in trainings that uses Lego to create a city, building a tower with marshmallows and spaghetti, but the most recent training that I had was using stacks of cards to simulate a development process.

Key Findings in Report

In the report, there are some key findings after all the survey was executed and analyzed, all of them are interesting, and similar to the organizational changes, I’ll comment in just a few.

  • “Many organizations are adopting an ad-hoc approach to agile: 21% of respondents use Agile when/where needed, and 23% use it within specific functions. However, adoption needs to be enterprise-wide (and consistent) to realize real results.”

I agree that the adoption must be enterprise-wide, and I want to believe it, however the reality is not that. As the same survey expose, the number of companies that have adopted agile in every area of the company is less than 10%, and that’s because it’s not a simple process. Implementing an ad-hoc approach is a middle ground solution, that will reduce costs and obtain benefits.

Agile Adoption

Personal creation based on report data
  • “Not everyone eagerly embraces agility: Longtime employees (29%) are the biggest detractors of organizational agility and may stand in the way of widespread adoption. This is a prime opportunity for senior-level executives to address employee concerns and shift mindset.”

It’s true that longtime employees are one the of the biggest detractors, but that’s because the resistance to change is stronger in them (Star Wars jokes aside :). However, I wouldn’t limit this to just a group of people. There was one time that I had someone assigned that didn’t believed in Scrum, and it was due to a bad experience before where the execution was done incorrect; for example Sprint Plannings of 3 hours, DSUs of more than 30 minutes and other bad practices.

  • Many organizations eliminate hierarchy in the hopes of increasing agility: 44% of survey respondents have introduced a flatter structure to become more Agile. But that may be premature; Agile is about creating the right dynamics for teams to iterate quickly, not simply moving boxes around on organizational charts.

For this one, I believe that changing the structure is good, simplifying it and making it more easy to work with. However, I don’t believe that you need to flat every structure. There are frameworks like LeSS (Large Scale Scrum) that help making organizations more lean and scale scrum across all of it.


Moving to an agile process is not easy, evidenced by this survey. There will always be changes required, trainings needed and a really good management. If you are interested, read the whole report from the Scrum Alliance, there are really good insights to incorporate to your own company.

If you have any comment, don't hesitate in contacting me or leaving a comment below. And remember to follow me on twitter to get updated on every new post.

Node.js and ORMs? TypeORM at your service

As I’ve mentioned in other posts, I’m working with more Node.js projects than ever and my experience with .NET applications is reducing (not complaining, if you think that). However, most of those projects have been with no-sql databases like DynamoDB and I haven’t had the need to use any ORM for it, even though there are options.

Recently, I was assigned a project that needed a big rescue. It’s an internal application of the company, rewritten many times but none of those times it has been completed, and the design itself wasn’t as good as you would like it to be. My assignment, design the architecture, define the technologies to be used, estimate it and assign tasks to a group of developers to work on it. So far, so good.

I decided to use React in the front end, and one main REST service in ExpressJS. Both solutions are going to be written in typescript. But what about the database? well, mysql was my choice and if you ask me the reason, it’s because the business logic makes more sense in a relational environment, but also because I want that my team (and myself) use an ORM to connect to a relational database like MySQL.

A quick search in Google will give you many results about ORMs but I found an interesting article that compares many of them and gives them a rank, take a look at it here. The only comment I would make there is that mongoose is limited to only one database, whereas TypeORM support multiple ones so in my mind, they should switch positions.

Ok, enough chit-chat, let’s start with the tech-y comments. First, I’m starting with a simple definition on an ORM.

What’s an ORM?

ORM stands for Object Relational Mapping, and it’s a mechanism that enables developers to manipulate data directly from the source without the hassle that it normally would take. They map the data sources to objects in code that can be queried, and the ORM transforms the actions over those objects to the specific commands in the specific data source. In other words, they abstract the data access layer from the developers and serves a “virtual object database” to be used within the programming language.

There are many ORM tools in the community, here are some of the most famous ones per programming language:

  1. Hibernate -> Java

  2. Entity Framework -> C#

  3. CakePHP -> PHP

  4. Django -> Python

  5. ActiveRecord -> Ruby

What’s TypeORM?

As the name suggests, and we have mentioned many times over the post, it is an ORM that runs in NodeJS; however it supports other environments like PhoneGap, React Native, Nativescript, etc.

It’s built to be used with Typescript or the latest versions of Javascript (from 5 to 8). Currently, version number is 0.2.9, but do not get fooled by this, it has over 3000 commits in Github! more than 40 thousand downloads per week! and finally, but not least, over 9000 stars!

The first version was deployed in December 6th of 2016, and had 36 releases since then. Being a young tool, it has been influenced by other ones like Hibernate and Entity Framework, so if you noticed stuff that feel familiar, it’s because they are.

From their website, here are some of the main features it provides:

  1. Both DataMapper and ActiveRecord

  2. Eager and Lazy relations

  3. Multiple inheritance patterns

  4. Transactions

  5. Cross-database queries

  6. Query caching

  7. Support for 8 different databases

  8. And many more here

Is there a model generator?

If you have worked with Entity Framework, you can do reverse engineering to create all the POCO classes from an existing database. Well, for TypeORM there is something similar.

Konnonable’s typeorm-model-generator package solves all of this for you. It can create all the object classes that you need to use in your application and it supports 6 databases, leaving Mongo and sql.js outside of the equation.

This package is even younger than typeorm, its first release was in July 2017 and it had 24 releases since then. It’s far less known in the community since there are not many downloads per week according to npmjs (around 300 per week).

Still, this package works like a charm and the configuration is as simple as you can imagine. Take a look at the next line:

typeorm-model-generator -e mysql -h [HOSTNAME] -d [DATABASE] -u [USER] -x [PASSWORD] -p 3306 --noConfig -o . --cf camel --ce pascal --cp camel --lazy

From it you can specify all the necessary parameters to establish a connection to a database, but also some configurations regarding the classes generated like the naming conventions and the “lazyness” of the relationships between them. If you want to take a look at all the available options for configuration, click here to view them.

Using TypeORM

After creating the classes with the typeorm-model-generator package, I ended up having classes that look something like this one:

import { Index, Entity, Column, OneToOne, OneToMany, ManyToOne, JoinColumn } from "typeorm";
import { UserStatus } from "./userStatus";
import { ProjectMember } from "./projectMember";
import { StatusReport } from "./statusReport";
import { TimeOff } from "./timeOff";

@Entity("User", { schema: "statusone" })
@Index("StatusTxt", ["statusTxt",])
export class User {
    @Column("varchar", {
        nullable: false,
        primary: true,
        length: 50,
        name: "UserNm"
    userNm: string;

    @Column("varchar", {
        nullable: false,
        length: 150,
        name: "Email"
    email: string;

    @Column("varchar", {
        nullable: false,
        length: 150,
        name: "FullNm"
    fullNm: string;

    @ManyToOne(() => UserStatus, UserStatus => UserStatus.users, { nullable: false, onDelete: 'RESTRICT', onUpdate: 'RESTRICT' })
    @JoinColumn({ name: 'StatusTxt' })
    userStatus: Promise<UserStatus | null>;

    @OneToOne(() => ProjectMember, ProjectMember => ProjectMember.userNm, { onDelete: 'RESTRICT', onUpdate: 'RESTRICT' })
    projectMember: Promise<ProjectMember | null>;

    @OneToMany(() => StatusReport, StatusReport => StatusReport.userNm, { onDelete: 'RESTRICT', onUpdate: 'RESTRICT' })
    statusReports: Promise<StatusReport[]>;

    @OneToMany(() => TimeOff, TimeOff => TimeOff.userNm, { onDelete: 'RESTRICT', onUpdate: 'RESTRICT' })
    timeOffs: Promise<TimeOff[]>;

This one is an easy example of a User table in our database with its relationships like the status of the user, all the reports and more.

TypeORM uses heavily decorators, which requires some options to be enabled in the tsconfig file, however don’t worry about them since it’s explained in their installation instructions here. But if you want the easy route, here is mine.

  "compileOnSave": false,
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "esModuleInterop": true,
    "sourceMap": true,
    "moduleResolution": "node",
    "outDir": "dist",
    "typeRoots": ["node_modules/@types"],
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  "include": ["typings.d.ts", "server/**/*.ts", "src/**/*.ts"],
  "exclude": ["node_modules"]

Ok, so our project have the classes from the database, and the typescript compiler recognizes all the decorators that TypeORM uses, so how do I use it??

I’m not going to expose the architecture I’m planning on using in the application, mostly because I haven’t completed it. But here is an example of a basic query I’ve done with TypeORM.

import {createConnection} from "typeorm";
import {User} from "../data-access/entity/User";

createConnection().then(async connection => {
      try {
        const users = await connection.manager.find(User);
        console.log("Loaded users: ", users); 
      } catch (error) {
    }).catch(error => console.log(error));

Just as easy as it looks, you can obtain all the users from the database by creating a connection, and then using the connection manager to find all the objects from the class passed as parameter.

Another more complex query can be the following:

import {createConnection} from "typeorm";
import {User} from "../data-access/entity/User";

createConnection().then(async connection => {
      try {
        let projectMembers = await connection
            .innerJoinAndSelect("user.projectMember", "projectMember")
        console.log("Loaded members: ", projectMembers); 
      } catch (error) {
    }).catch(error => console.log(error));

In this example, we are creating a query that retrieves the relationship to ProjectMember for the users using a syntax called QueryBuilder which reminds me a lot of EntityFramework.

As far as query examples goes, I will stop here and suggest you to read more documentation like here or here.

Is there anything bad?

Nothing is perfect in this world, and I didn’t have to investigate a lot to find something that surprised me. Believe it or not, but apparently TypeORM still doesn’t support bit types for mysql (Check line 81 in this file).

Even though that this shocked me at first, I had the possibility of changing the design to overlook those bit types and use something different, however it’s still something that annoys me and they should add that support soon.


TypeORM is one more tool to our toolkit, one that will make your life a lot easier and have the support of a big community. It allows you to abstract a lot of the complex code that can come from connecting to a database, and helps you focus on your business instead of figuring out how to do a select in a table.

If you have any comment, don't hesitate in contacting me or leaving a comment below. And remember to follow me on twitter to get updated on every new post.

Use Athena To Process Data From DynamoDB

Have you ever thought that it would be so good to have SQL-like queries in DynamoDB?

I worked in companies that have always used Microsoft's SQL Server as database, and it's so easy for me to do things like COUNT, AVG, among others to calculate metrics and other indicators. However, now that I've been using Dynamo for some projects, I miss that.

This week, I found Athena (not the Greek Goddess), a tool provided by Amazon to query big data information stored in S3 using standard SQL queries. To use it, you don't need to configure any infrastructure, it runs serverless and executes the queries directly into the datasource in S3. It supports a variety of data formats like CSV, JSON, among others (today, we will be doing some examples using JSON).

But then, how do I use it to query from Dynamo? well, Athena still does not support queries directly into Dynamo, but we can mimic this functionality by using AWS Glue.

AWS Glue, is another tool that allows developers to create ETL jobs that can perform many tasks, and it's completely integrated with Athena. AWS Glue uses something called Crawlers that create schemas from the datasources that are analyzed, so for example, creating a crawler from a dynamo table, will enumerate all the columns that the table can have and a possible type of the data it contains.

So combining everything, we can do the following:

  1. Create a crawler that reads the Dynamo table
  2. Create a Glue job that reads the information and stores it in an S3 bucket
  3. Create a new crawler that reads the S3 bucket
  4. Use Athena to query information using the crawler created in the previous step.
  5. Expose information using API Gateway and Lambda functions

Here you have a visual representation of those steps:

And here is an example of the queries that you can create:

SELECT a.openCount, b.openWACount, c.solvedYTD
   SELECT COUNT(*) AS openCount
   FROM caseview_metrics
   WHERE status='open'
) a
   SELECT COUNT(*) AS openWACount
   FROM caseview_metrics
   WHERE status='open' AND CARDINALITY(abductorsids) >= 1
) b
   SELECT COUNT(*) as solvedYTD
   FROM caseview_metrics
   WHERE status='close' AND closeddate BETWEEN 1514764800000 AND 1546300799000
) c

In this example, you can see functions as COUNT or CARDINALITY, expressions like BETWEEN or comparisons, and finally you can also apply JOIN clauses like the CROSS JOIN.


AWS Athena is a tool that you can add to your toolkit, and if you are using Dynamo, it can enhance greatly the experience for the users, as well as facilitate development. 

If you have any comment, don't hesitate in contacting me or leaving a comment below. And remember to follow me on twitter to get updated on every new post.

Tech Review: NativeScript

Mobile development is a world that, for me, is different than what I'm used to work with. I come from a .NET background and moved recently to a Full Stack Javascript developer, but I wanted to dive a little bit in creating mobile applications. After reading a lot, I saw that there is a bunch of technologies that abstract the native development into a different stack. Maybe, if you have reached this post, you have seen options like:

  1. Apache Cordova
  2. PhoneGap
  3. Ionic
  4. React Native
  5. Xamarin

However, this post, as the title suggest, is about NativeScript. A smaller contender that is trying to grow and compete on equal terms with the others. 

As we can see, comparing searches using Google Trends between NativeScript, Apache Cordova and PhoneGap demonstrates that there is a steady growth for our contender. But, if we do the same comparison against Xamarin or React Native, we will see that there is a big gap that need to be closed.

NativeScript is an open-source framework that builds native applications using other frameworks such as Vue.js or Angular and languages like Typescript or Javascript. It became publicly available in March 2015, so it's a relatively young technology (you might differ, in this world, two years is enough for something to be called old, haha). Since then, there has been 41 releases, with the current version being 4.1.1.

As I stated before, NativeScript is a framework that uses web technologies to create native applications, so this is a big advantage for web developers; having the ability to use the skills possessed to create mobile applications, is a really good selling point.

On Github, it possess more than 14.000 stars, 114 contributors and a really active community, you can follow the repository and see the activity in the issues feed. According to npm, it's licensed under Apache2.0, and it has more than 35.000 downloads per week. 

Even with those numbers, you might still question yourself if it's worthy to work with, well, there are companies that decided to trust on it; big companies like Bosch, Samsung, Qualcomm and others. 

How does it work?

Ok, enough with the introduction, let's move to more interesting topics. To explain how it works, here is a really good extensive post explaining that, but I'm going to explain it briefly now.

In short words, NativeScript uses Javascript virtual machines that are used to execute commands (V8 for Android and JavascriptCore for iOS). These machines execute the code compiled in JIT format that is then transformed to the native counterparts for each operative system. Also, if you are familiar with Reflection, NativeScript uses it to inject the available APIs to match with the Javascript versions of them. 

Using Nativescript

In this post, I'm not going to cover how to install NativeScript, for that, follow the quick setup installation guide from their official site. Also, one of the reasons I used NativeScript is the fact that it integrates with Angular easily, hence, I will not only focus on NativeScript, but also in how to use it with Angular. So, assuming you have a working environment and you are interested in using Angular, let's continue.

The main aspects I will cover for now are: typescript code to bind events and layouts examples, in a later post, I will do a more complete tutorial.

Layout examples

Even though that we are using web technologies like Javascript, the layouts change drastically. The HTML tags we know are no longer usable, instead, there are defined tags that we need to use, they are:

  1. AbsoluteLayout: it uses specific coordinates to allocate items inside of it. 
  2. DockLayout: it allocates items to the edges of the layout (top, bottom, left or right).
  3. GridLayout: it is useful to accommodate items in a table structure where you define the number of rows and columns.
  4. StackLayout: as the name suggests, this layout stacks its children based on the orientation defined.
  5. WrapLayout: this layout works similar to the StackLayout, however, when the items don't have any room left, it continues stacking them in a new row.
  6. FlexboxLayout: this layout mimics the CSS box layout.

Here is an example using some of these layouts:

<StackLayout class="menu-bg" orientation="vertical">
  <StackLayout orientation="horizontal" horizontalAlignment="center" height="100%">
    <DockLayout class="home-menu-container" stretchLastChild="true" verticalAlignment="middle">
      <Label dock="top" class="h1" [text]="title"></Label>
      <StackLayout dock="bottom" class="menu-options" orientation="vertical" verticalAlignment="middle">
        <Button text="Start New Game" class="button new-game" (tap)="onNewGameTap()"></Button>
        <Button text="Options" class="button options" (tap)="onOptionsTap()"></Button>

We can still use classes as in HTML to assign styles using CSS or SCSS files. Other tags like Labels and Buttons also changed a little bit from their counterparts in HTML, labels for example use a text attribute to assign the value and buttons' click events are replaced with tap events.

Event and property binding

Like using Angular in a web page, we create components that will be rendered in the application. These components will handle some UI logic and call other providers or services that will handle the business logic. From these components, we will assign events or properties that will be bound by the two-way binding feature from Angular by using the proper wrappers. In the example we had before, we can see the following bindings:

  1. The label tag has a text property wrapped in square brackets that maps to the title property on the component.
  2. The button tag has a tap event wrapped in parenthesis that calls the onNewGame event on the component.

Here is the matching code example:

import { Component } from '@angular/core';
import { RouterExtensions } from 'nativescript-angular/router';
import { NEWMAZE, CONTINUEMAZE } from '~/shared/constants';

    selector: 'menu',
    templateUrl: './menu/menu.component.html',
    styleUrls: ['./menu/menu.component.css']
export class MenuComponent {    
    title: string = "New Game"
    constructor(private router: RouterExtensions) { }
        this.router.navigate([`maze/${NEWMAZE}`], { clearHistory: true });

        this.router.navigate(["options"], { clearHistory: true });


NativeScript is a great framework that is growing in the community, hopefully, it will match others like Xamarin and React Native, but so far, the experience to develop on it has helped me to create mobile applications fast and easily. Even though that I've found some things that weren't easy to fix, there are always workarounds available. Hopefully, I will create a new post that will go deeper in details and maybe a tutorial, stay tuned.

If you have any comment, don't hesitate in contacting me or leaving a comment below. And remember to follow me on twitter to get updated on every new post.