Getting Started

Basics

Query Modifiers

.where() .sort()

Query Predicates

.equals() .notEquals() .exists() .notExists() .startsWith() .endsWith() .contains() .greaterThan() .lessThan() .between() .outside()

Query Executors

.read() .first() .last() .count() .sum() .average() .min() .max() .update() .delete()

Login Methods

.exists() .login() .logout()

Instance Methods

.read() .delete()

Instance Login Methods

.login() .logout() .changePassword()

Misc

Back.then() Back.saved() Back.user() Back.eachProperty() Back.eachDescendant() IFile Property LoginResult

Overview

Back I/O is a platform that allows you to build complex web and mobile JavaScript applications without involving a backend developer or server operations team. There is nothing to install, no servers to manage, and no ops-duties to perform. Back I/O is completely independent of any front-end framework, so it fits well with Angular, React, Cordova, etc.

Code Generation

Backends in Back I/O are created in a 2 step process. First, an object model with relationships is layed out in a purely object-oriented fashion. If you have experience with relational models, you'll need to stop thinking in terms of primary keys, foreign keys, join tables, and start thinking in terms of objects, properties, and arrays that reference other objects.

Next, the object model is deployed to one of the two provided environments (debug or production). Once this is complete, a custom JavaScript library is generated (along with TypeScript typings), which is then dragged and dropped into the source code repository. This JavaScript library is loaded with a series of "hot" constructors that represents the data model. These are JavaScript constructors that return objects that, when accessed, automatically stream the updates for storage on the back end.

The behavior of these returned objects have been carefully architected to preserve the standard behavior of JavaScript. Using a hot object should be identical to any other object, except that their members are persisted on the back end.

Structuring Data

Back I/O's unique object oriented model allows apps to be structured in ways that would be difficult or impossible to represent in a uni-directional tree-based data structure (JSON). Back I/O data models can have many-to-many relationships, cyclical relationships, and even self-referencing types.

Back I/O objects preserve referential integrity. For example, assume that a query is made to the server that returns objects A, B, and C. The application holds references to these 3 objects, and uses them as the backing data store for the user interface. Then, another query is made that returns objects B, C, and D. In this case, Back I/O is smart enough to update the pre-existing objects B and C (that application currently references), and create a new object D, rather than simply creating 3 new objects, and leaving it to the application developer to manage multiple proxy objects that map to the same underlying data store.

Simple Usage Example

// Create & save a new employee
var employee = new Employee();
employee.name = "Paul";

// Add some people underneath this employee.
employee.supervisedEmployees.push(new Employee());

// Upload an avatar
employee.avatar.file = $("INPUT[type=file]");

Reading Data through Plurals

The generated JavaScript library also contains what we call Constructor plurals. Every generated constructor also has a corresponding plural, named according to the the English pluralization rules, such that for Company, there is Companies, and for Employee, there is Employees. The purpose of the plural is to give an entry point into beginning in object query that will hopefully result in some objects being loaded.


Employees
	.where(Employee.salary).greaterThan(2500)
	.where(Employee.favouriteColor).equals("white")
	.read(results =>
	{
		// results is an array, where each item is instanceof Employee.
	});

// Authentication operations are considered 
// to be a form of object query, to the operation
// starts with the plural.
Employees.login("employee@company.com", "pass", returnedEmployee =>
{
	var success = returnedEmployee !== null;
});