The Todo Model

Let's create your first model. The CLI provides a useful command to generate a new file with an empty model.

foal generate entity todo

FoalTS uses TypeORM, a complete Object-Relational Mapper, to communicate with the database(s). In TypeORM, simple models are called entities and are classes decorated with the Entity decorator.

Every new project in FoalTS uses an SQLite database as it does not require any additional installation. But TypeORM supports many other databases. We will keep this one in this tutorial for simplicity.

Open the file todo.entity.ts in the src/app/entities directory and add a text column.

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Todo {
@PrimaryGeneratedColumn()
id: number;
@Column()
text: string;
}

This class is the representation of the SQL table todo. Currently, this table does not exist in the database. You will have to create it.

You can do this manually, using a database software for example, or use migrations, a programmatic way to update a database schema. The advantage of using migrations is that you can create, update and delete your tables directly from the definition of your entities. They also ensure that all your environments (prod, dev) and co-developpers have the same table definitions.

Let's see how to use them.

First compile the application.

npm run build:app

Then run the following command to generate your migration file. TypeORM will compare your current database schema with the definition of your entities and generate the appropriate SQL queries.

npm run migration:generate -- --name=add-todo-entity

A new file appears in the src/migrations/ directory. Open it.

import {MigrationInterface, QueryRunner} from "typeorm";
export class addTodoEntity1562755564200 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`CREATE TABLE "todo" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "text" varchar NOT NULL)`);
await queryRunner.query(`CREATE TABLE "user" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL)`);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`DROP TABLE "user"`);
await queryRunner.query(`DROP TABLE "todo"`);
}
}

The up method contains all the SQL queries that will be executed during the migration.

Let's compile and run the migration.

npm run build:migrations
npm run migration:run

TypeORM examines all the migrations that have been run previously (none in this case) and executes the new ones.

Your database (db.sqlite3) now contains a new table named todo:

+------------+-----------+-------------------------------------+
| todo |
+------------+-----------+-------------------------------------+
| id | integer | PRIMARY KEY AUTO_INCREMENT NOT NULL |
| text | varchar | |
+------------+-----------+-------------------------------------+

Alternatively, you can also use the synchronize option in your configuration file config/default.json. When set to true, the database schema is auto created from the entities definition on every application launch. You do not need migrations in this case. However, if this behavior is useful during debug and development, it is not suitable for a production environment (you could lose production data).