Page Contents

Overview

In LoopBack, auto-migration helps the user create relational database schemas based on definitions of their models. Auto-migration can facilitate the synchronization of the backing database and models so that they match, such as in cases where the database needs to be changed in order to match the models. LoopBack offers two ways to do this:

  • Auto-migrate: Drop schema objects if they already exist and re-create them based on model definitions. Existing data will be lost.

  • Auto-update: Change database schema objects if there is a difference between the objects and model definitions. Existing data will be kept.

Implementation Example

Below is an example of how to implement automigrate() and autoupdate(), shown with the TodoList example.

Create a new file src/migrate.ts and add the following import statement:

import {DataSource, Repository} from '@loopback/repository';

Import your application and your repositories:

import {TodoListApplication} from './index';
import {TodoRepository, TodoListRepository} from './repositories';

Create a function called dsMigrate():

export async function dsMigrate(app: TodoListApplication) {}

In the dsMigrate() function, get your datasource and instantiate your repositories by retrieving them, so that the models are attached to the corresponding datasource:

const ds = await app.get<DataSource>('datasources.db');
const todoRepo = await app.getRepository(TodoRepository);
const todoListRepo = await app.getRepository(TodoListRepository);

Then, in the same function, call automigrate():

await ds.automigrate();

This call to automigrate will migrate all the models attached to the datasource db. However if you want to only migrate some of your models, add the names of the classes in the first parameter:

// Migrate a single model
ds.automigrate('Todo');
// Migrate multiple models
ds.automigrate(['Todo', 'TodoList']);

The implementation for autoupdate() is similar. Create a new function dsUpdate():

export async function dsUpdate(app: TodoListApplication) {
  const ds = await app.get<DataSource>('datasources.db');
  const todoRepo = await app.getRepository(TodoRepository);
  const todoListRepo = await app.getRepository(TodoListRepository);

  await ds.autoupdate();
}

The completed src/migrate.ts should look similar to this:

import {DataSource, Repository} from '@loopback/repository';
import {TodoListApplication} from './index';
import {TodoRepository, TodoListRepository} from './repositories';

export async function dsMigrate(app: TodoListApplication) {
  const ds = await app.get<DataSource>('datasources.db');
  const todoRepo = await app.getRepository(TodoRepository);
  const todoListRepo = await app.getRepository(TodoListRepository);

  await ds.automigrate();
}

export async function dsUpdate(app: TodoListApplication) {
  const ds = await app.get<DataSource>('datasources.db');
  const todoRepo = await app.getRepository(TodoRepository);
  const todoListRepo = await app.getRepository(TodoListRepository);

  await ds.autoupdate();
}

Finally, in src/index.ts, import and call the dsMigrate() or dsUpdate() function:

import {TodoListApplication} from './application';
import {ApplicationConfig} from '@loopback/core';

// Import the functions from src/migrate.ts
import {dsMigrate, dsUpdate} from './migrate';

export {TodoListApplication};

export async function main(options: ApplicationConfig = {}) {
  const app = new TodoListApplication(options);
  await app.boot();
  await app.start();

  const url = app.restServer.url;
  console.log(`Server is running at ${url}`);

  // The call to dsMigrate(), or replace with dsUpdate()
  await dsMigrate(app);
  return app;
}