Erbix

Home > Developer Tutorial

Overview

This tutorial presents, step-by-step, how to get started with Erbix from a developer perspective, in order to be able to use Erbix to create online apps.

The tutorial includes the initial concepts regarding server-side JavaScript programming, presents a Hello World application and explains how to set it up on a website hosted on Erbix.

JavaScript Everywhere

The most popular form of JavaScript is the one offered by today's web browsers in order to execute specific instructions regarding the content of a HTML webpage after it finished loading inside the browser.

This programming environment, known as client-side JavaScript, has two distinct parts:

  • the core JavaScript language, the one including keywords like var, for or if.
  • the variables and functions exported by the browser, such as alert, confirm or the document DOM (Document Object Model), which allows page authors to access and manipulate the webpage.

In this way, JavaScript, a language which by itself has no knowledge of HTML or document nodes, has been modified to be aware of special bindings inserted by the browsers in order to be able to manipulate webpages.

Recently a new idea emerged: instead of using languages like PHP, Java, Python or Ruby in order to specify how an app's webserver should respond to the incoming HTTP requests, let's use JavaScript. Just like in the case of browsers, specific bindings need to be exposed to enable developers to do things like database SQL interaction or file I/O operations, but the core of the language is kept unmodified. This is called server-side JavaScript.

CommonJS and Modules

Initially, several server-side JavaScript bindings appeared. Relatively soon, the need for standardization and inter-operability between them became obvious.

Folks gathered under what is known today as the CommonJS project. The group aims to provide a standard library that an application developer will be able to use in order to run his CommonJS complaint code across different JavaScript interpreters and host environments.

Despite being at the beginning of their efforts with a bold mission to pursue in the foreseeable future, CommonJS managed to lay a solid foundation by establishing a compartimentalization model called modules which allows library-like separation in JavaScript: the variables are no longer global, instead they are limited at the module level and have to be manually exported to gain visibility in other parts of the code.

A Modules/1.1.1 Example

There are different versions of the modules specification. Erbix uses Modules/1.1.1.

In Erbix, a module is a single .js file in which there are 3 keywords with special meaning:

  • exports is an existing hash which accepts new keys as a way to export variables and functions in order to gain visibility outside the current module.
  • require is an existing function which accepts one parameter identifying an external module path and returns a hash with all the exported variables and functions by that module.
  • module is a read-only existing hash containing information about the current module (such as module.id).

Here's an example with two module files:

ageToMonths.js, the first module, contains a function converting a specific number of years into months. Notice how exports is being used.

function ageToMonths(years) {
  return years * 12;
}
exports.ageToMonths = ageToMonths;

ageAdder.js, the second module, uses the first module and contains a function that takes as input two age variables in years and returns the total number of months that would have been lived by two persons having said ages. Notice how require is being used.

function adder(years1, years2) {
  return require('ageToMonths.js').ageToMonths(years1 + years2);
}

JSGI and a Hello World Example

The other important specification of the CommonJS group is called JSGI.

JSGI comes from JavaScript Server Gateway Interface; it defines a standard regarding how a function should look like in order to be able to communicate with a webserver regarding an incoming HTTP request and the response that should be returned to the user.

Erbix currently uses the JSGI/0.3 version. The standard is relatively simple and defines the input and the output that such a function should provide.

Input:

  • request: an unique input parameter containing different keys that indicate details about the incoming request. The full list can be found in the specification, but the most important key is request.pathInfo, which contains the path of the URL requested by the client (found in the URL after the domain hostname and the app prefix, if any).

Output - a hash containing the following 3 keys:

  • status - numeric field indicating the status code of the reply, according to rfc2616.
  • headers - hash of key/value pairs reflecting header names and corresponding values in the reply. The most important key, "Content-type", should be associated with a "text/plain" value in case of outputing plain text, or with "text/html" in case HTML markup is being returned in the body.
  • body - array of strings representing the body of the reply.

The following code is a Hello World implementation in JSGI which displays the text Hello World for the homepage and returns the error code 404 HTTP Not Found for other requests.

  exports.mainFunction = function (request) {
    if ((request.pathInfo !== "") && (request.pathInfo !== "/")) {
      return {
        status: 404,
        headers: {
          "Content-Type": "text/plain"
        },
        body: ["Page not found."]
      };
    }

    return {
      status: 200,
      headers: {
        "Content-Type": "text/plain"
      },
      body: ["Hello World! Here's a random number: " + Math.random()]
    };
  };

Erbix App Deployment

In Erbix, an account has one or more domains, usually following the pattern <domain-name>.erbix.com.

The previous code (which is a JSGI function) can be deployed on a domain on a path prefix: http://<domain-name>.erbix.com/<path-prefix>. This means that the request.pathInfo variable will contain what follows after the path prefix (and accessing the domain path prefix is equivalent with an empty or "/" value for the pathInfo).

To make the deployment, in the Files tab let's add a new file (using the 'Add new file' link in the lower-left side of the screen) called myApp/main.js. The file should contain the code given above as example.

To deploy this code on a domain, select the Configure Apps tab and click the Add a new entry-point function button corresponding to the domain where the app should be deployed. The fields should indicate:

  • the JS module file path containing the JSGI function (myApp/main.js)
  • the JSGI function name inside that file (the one receiving the request parameter) - mainFunction
  • the URL prefix on that domain where the app should run - either / or a more specific path if we want to keep the domain homepage free, to be available for other purposes.

After clicking the Add button, the app should be up and running at the configured location.

Creating an SQL table

The Erbix account interface offers a SQL Console tab for executing debug or one-time SQL statements (such as table creation).

Let's say we want to create an SQL table with 3 columns: id, name and surname. The table will be used to record a list of customers and to associate an id as a reference key for every such customer.

Erbix offers for each account an associated PostgreSQL database. The PostgreSQL documentation contains useful examples, including the examples for the CREATE TABLE command.

Once the table structure is settled, the CREATE TABLE command should be launched in the SQL Console tab. Let's use the following as example:

CREATE SEQUENCE customer_id_seq START 100;
CREATE TABLE customers(
     id      integer PRIMARY KEY DEFAULT nextval('customer_id_seq'),
     name    varchar(40) NOT NULL,
     surname varchar(40) NOT NULL
);

After running this statement, the table name should appear in the list of tables found in the database associated with this account (on the right-side panel of the SQL Console tab).

We can check if everything is ok by inserting a row and querying the table again in the SQL Console tab:

INSERT INTO customers(name, surname) VALUES('John', 'Doe');
SELECT * FROM customers;

The console output should display the John Doe row as a result of executing these statements.

Running SQL inside the app

Let's say we want to see the entire list of our customers as stored in this table each time we access the /list URL.

The first step is to add an if statement dealing with this URL at the beginning of the JSGI function:

  if (request.pathInfo === "/list") {
    return {
      status: 200,
      headers: {
        "Content-Type": "text/plain"
      },
      body: [getCustomerList()]
    };
  }

The following code should be placed in the same file, in order to define the behaviour for the newly introduced getCustomerList() function:

getCustomerList = function () {
  var connection = require("erbix/query").getConnection();
  var statement = connection.createStatement();
  var resultSet = statement.executeQuery(
      "SELECT id, name, surname FROM customers");

  var returnText = "";
  while (resultSet.next()) {
    returnText +=
      resultSet.getObject(1) + " / " +
      resultSet.getObject(2) + " / " +
      resultSet.getObject(3) + "\n";
  }
  return returnText;
};

After these modifications, accessing the /list URL on the configured domain should return "1 / John / Doe" as output.

Future Resources

To continue learning about Erbix and how to write JS webapps in the browser you can use the following resources:

  • install the Erbix Tutorials from the AppStore and check the code behind those examples.
  • consult the JS Reference docs with further details about the topics that are of interest to you.
  • tell us your feedback - we are extremely enthusiastic to hear from you and to get Erbix in a better shape by addressing the issues that you've encountered.

Thanks for choosing Erbix!
- the Erbix team