Skip to main content

Getting Started

Overview

This 10 minute read will cover:

  1. Installation
  2. Creating custom endpoints
  3. Generating Create, Read, Update, Delete endpoints
  4. Realtime Functionality with Socket.io
  5. File Uploads

Installation

Make sure you have Node installed.

npx ezbackend init my-ezbackend

Replace my-ezbackend with your-folder-name or . for current dir.

This creates a basic boilerplate for you to develop your app from, which can be found in src/index.ts.

Running your backend

You can run the boilerplate code with:

npm start

You'll have a working backend running on:

localhost:8000.

A User Interface will also be generated at:

localhost:8000/db-ui

The user interface provides:

  1. Automated API Documentation (Which can also be used to test Endpoints)
  2. Database Editing Interface

Creating HTTP Endpoints

You can create an HTTP endpoints with EzApps, which are the building blocks of ezbackend.

The syntax is similar to express.js.

The below code creates a POST endpoint at /echo accepts a JSON input of {'input':message} and echos an output of {'output':message}.

const app = new EzBackend()

const echo = new EzApp()

echo.post('/', async (req,res) => {
return {output: req.body.input}
})

app.addApp(echo, {prefix:'echo'}) // Prefix the all the EzApp routes with '/echo'

app.start() // Start the backend
info

Throughout the tutorial, if you need a fully working, copy-pastable example, you can click on Full Sample.

To test the endpoint, we need to specify the input schema. We can do this using Typescript classes. (Or JSON Schema if you are using vanilla js)

// Use class for automated documentation
export class EchoInput {
input: string
}

const echo = new EzApp()

echo.post('/', {
body: EchoInput // Tell EzBackend to expect EchoInput as the request body
}, async (req, res) => {
return { output: req.body.input }
})

app.addApp(echo)

app.start()

You can test your echo endpoint from the DB UI.

Defining your input and output explicitly provides:

  1. Input/Ouput Validation
  2. Automated Documentation for Frontend Engineers
  3. Faster Endpoints
  4. Typescript support within endpoint handlers

You can provide additional metadata for routes to provide better documentation for your frontend developers.

echo.post('/', {
body: EchoInput,
reply200: EchoOutput,
summary: "Echo Route",
description: "Accepts a JSON input of {'input':message} and echos an output of {'output':message}"
}, async (req, res) => {
return { output: req.body.input }
})

Connecting to the Database

EzBackend's built models have multiple purposes:

  1. As an ORM (Object Relational Mapping) library
  2. To generate CRUD (Create Read Update Delete) Routes
const pets = new EzModel(
"Pet", // Table Name
{
name: Type.VARCHAR,
age: Type.FLOAT,
species: {
type: Type.ENUM,
enum: ['cat','dog','rabbit']
},
}
)

app.addApp(pets, {prefix: 'pets'})

What the above code does is:

  1. Create a table in your database called Pet
  2. Create the columns in your database name,age and species
  3. Create CRUD (Create, Read, Update, Delete) endpoints under the route prefix pets

You can test the CRUD endpoints from the DB UI.

If you wish to create a table but not the CRUD endpoints you can use EzRepo instead.

const pets = new EzRepo("Pet", {...})

You can create your own endpoints on an EzRepo/EzModel because they are childs of EzApp.

pets.get('/count',{
reply200: PetCount,
summary: "Get total pet count",
description: "Get the total number of pets"
},async (req, res) => {
const totalPets = await pets.count()
return { 'totalPets': totalPets }
})

In the above example, we used pets.count() to get the total number of pets. EzRepo and EzModel expose underlying typeorm Repository methods in order to help you access data in the database.

Some other common functions you can use are create, find, delete, createQueryBuilder.

Realtime Connection

By default, the CRUD routes generated by EzModel emit socket.io signals whenever entities are created, updated or deleted through those endpoints.

The emitted events follow the following format:

Socket.io NamespaceEvent NameArg 1Arg 2Caveats
/entity_createdEntity NameFull EntityOnly works when using EzBackend generated Routes
/entity_updatedEntity NameFull EntityOnly works when using EzBackend generated Routes
/entity_deletedEntity NameFull EntityOnly works when using EzBackend generated Routes

File Storage

You can add file storage with one line of code

const person = new EzModel("Person", {
name: Type.VARCHAR,
age: Type.FLOAT,
avatar: Type.FILE // Store file metadata and accept file uploads
})

This stores the file metadata in your database, and files in your filesystem under tmp/uploads by default.

In addition, multipart/formdata endpoints are automatically generated for you to be able to upload your files, and endpoints for downloading your files or displaying them are also available.

All data in the backend is handled with streams, meaning that any file storage functionality does not utilise an excessive amount of additional RAM.

Additional Configuration

By default, EzBackend uses SQLite as the database and the filesystem for handling uploads. However, EzBackend is fully customisable such that you can manage anything from the size of files being uploaded to the database being used, etc.

You can read more about configuration here

Shoulders of Giants

EzBackend is built on two well-known, battle tested packages, namely fastify and typeorm.

Hence, anything that is possible with fastify and typeorm is also possible within EzBackend.

However the value that EzBackend provides is the improved developer experience by providing a DRY interface and additional functionality on top of the two existing libraries.