Add TodoList Repository
LoopBack 4 TodoList Application Tutorial - Add TodoList Repository
Repositories with related models
One great feature of a related model‘s repository is its ability to expose afactory function (a function that returns a newly instantiated object) to returna ’constrained’ version of the related model‘s repository. A factory function isuseful because it allows you to create a repository whose operations are limitedby the data set that applies to the factory function.
In this section, we‘ll build TodoListRepository to have the capability ofbuilding a constrained version of TodoRepository.
Create your repository
From inside the project folder, run the lb4 repository command to create arepository for the TodoList model using the db datasource. The dbdatasource shows up by its class name DbDataSource from the list of availabledatasources.
lb4 repository
? Please select the datasource DbDatasource
? Select the model(s) you want to generate a repository TodoList
create src/repositories/todo-list.repository.ts
update src/repositories/index.ts
? Please select the repository base class DefaultCrudRepository (Legacy juggler
bridge)
Repository TodoListRepository was created in src/repositories/
From there, we‘ll need to make two more additions:
- define the
todosproperty, which will be used to build a constrainedTodoRepository - inject
TodoRepositoryinstanceOnce the property type fortodoshas been defined, usethis.createHasManyRepositoryFactoryForto assign it a repository constrainingfactory function. Pass in the name of the relationship (todos) and the Todorepository instance to constrain as the arguments for the function.
src/repositories/todo-list.repository.ts
import {Getter, inject} from '@loopback/core';
import {
DefaultCrudRepository,
HasManyRepositoryFactory,
juggler,
repository,
} from '@loopback/repository';
import {Todo, TodoList, TodoListRelations} from '../models';
import {TodoRepository} from './todo.repository';
export class TodoListRepository extends DefaultCrudRepository<
TodoList,
typeof TodoList.prototype.id,
TodoListRelations
> {
public readonly todos: HasManyRepositoryFactory<
Todo,
typeof TodoList.prototype.id
>;
constructor(
@inject('datasources.db') dataSource: juggler.DataSource,
@repository.getter(TodoRepository)
protected todoRepositoryGetter: Getter<TodoRepository>,
) {
super(TodoList, dataSource);
this.todos = this.createHasManyRepositoryFactoryFor(
'todos',
todoRepositoryGetter,
);
}
}
Inclusion of Related Models
To get the related Todo object for each TodoList, we have to override thefind and findById functions.
First add the following imports:
import {Filter, Options} from '@loopback/repository';
import {TodoListWithRelations} from '../models';
Add the following two functions after the constructor:
src/repositories/todo-list.repository.ts
async find(
filter?: Filter<TodoList>,
options?: Options,
): Promise<TodoListWithRelations[]> {
// Prevent juggler for applying "include" filter
// Juggler is not aware of LB4 relations
const include = filter && filter.include;
filter = {...filter, include: undefined};
const result = await super.find(filter, options);
// poor-mans inclusion resolver, this should be handled by DefaultCrudRepo
// and use `inq` operator to fetch related todos in fewer DB queries
// this is a temporary implementation, please see
// https://github.com/strongloop/loopback-next/issues/3195
if (include && include.length && include[0].relation === 'todos') {
await Promise.all(
result.map(async r => {
r.todos = await this.todos(r.id).find();
}),
);
}
return result;
}
async findById(
id: typeof TodoList.prototype.id,
filter?: Filter<TodoList>,
options?: Options,
): Promise<TodoListWithRelations> {
// Prevent juggler for applying "include" filter
// Juggler is not aware of LB4 relations
const include = filter && filter.include;
filter = {...filter, include: undefined};
const result = await super.findById(id, filter, options);
// poor-mans inclusion resolver, this should be handled by DefaultCrudRepo
// and use `inq` operator to fetch related todos in fewer DB queries
// this is a temporary implementation, please see
// https://github.com/strongloop/loopback-next/issues/3195
if (include && include.length && include[0].relation === 'todos') {
result.todos = await this.todos(result.id).find();
}
return result;
}
Now when you get a TodoList, a todos property will be included that containsyour related Todos, for example:
{
"id": 2,
"title": "My daily chores",
"todos": [
{
"id": 3,
"title": "play space invaders",
"desc": "Become the very best!",
"todoListId": 2
}
]
}
Let‘s do the same on the TodoRepository:
src/repositories/todo.repository.ts
async find(
filter?: Filter<Todo>,
options?: Options,
): Promise<TodoWithRelations[]> {
// Prevent juggler for applying "include" filter
// Juggler is not aware of LB4 relations
const include = filter && filter.include;
filter = {...filter, include: undefined};
const result = await super.find(filter, options);
// poor-mans inclusion resolver, this should be handled by DefaultCrudRepo
// and use `inq` operator to fetch related todo-lists in fewer DB queries
// this is a temporary implementation, please see
// https://github.com/strongloop/loopback-next/issues/3195
if (include && include.length && include[0].relation === 'todoList') {
await Promise.all(
result.map(async r => {
r.todoList = await this.todoList(r.id);
}),
);
}
return result;
}
async findById(
id: typeof Todo.prototype.id,
filter?: Filter<Todo>,
options?: Options,
): Promise<TodoWithRelations> {
// Prevent juggler for applying "include" filter
// Juggler is not aware of LB4 relations
const include = filter && filter.include;
filter = {...filter, include: undefined};
const result = await super.findById(id, filter, options);
// poor-mans inclusion resolver, this should be handled by DefaultCrudRepo
// and use `inq` operator to fetch related todo-lists in fewer DB queries
// this is a temporary implementation, please see
// https://github.com/strongloop/loopback-next/issues/3195
if (include && include.length && include[0].relation === 'todoList') {
result.todoList = await this.todoList(result.id);
}
return result;
}
We‘re now ready to expose TodoList and its related Todo API through thecontroller.
Navigation
Previous step: Add TodoList model
Last step: Add TodoList controller
