Skip to content

Commit

Permalink
feat: add "filter" parameter to "find" endpoints
Browse files Browse the repository at this point in the history
Modify the CLI template and example controllers to accept a new filter
argument, leveraging the recently added `@param.query.object()` and
Filter schema.

Rename the controller-method argument accepting model data from
`${controllerName}` to `data` (e.g. `data` instead of `TodoController`).
I think this was an oversight in the implementation of the REST
Controller template.

Update the code snippets in documentation that are showing controller
classes to match the actual code used in the examples and produced
by our `lb4 controller` command.
  • Loading branch information
bajtos committed Sep 25, 2018
1 parent ca8d96e commit 7e1acfc
Show file tree
Hide file tree
Showing 15 changed files with 417 additions and 94 deletions.
100 changes: 82 additions & 18 deletions docs/site/Controller-generator.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,17 @@ Here's an example of what the template will produce given a `Todo` model and a
`TodoRepository`:

```ts
import {Filter, Where, repository} from '@loopback/repository';
import {post, param, get, patch, del, requestBody} from '@loopback/rest';
import {Filter, repository, Where} from '@loopback/repository';
import {
post,
param,
get,
getFilterSchemaFor,
getWhereSchemaFor,
patch,
del,
requestBody,
} from '@loopback/rest';
import {Todo} from '../models';
import {TodoRepository} from '../repositories';

Expand All @@ -106,43 +115,98 @@ export class TodoController {
@repository(TodoRepository) public todoRepository: TodoRepository,
) {}

@post('/todos')
async create(@requestBody() obj: Todo): Promise<Todo> {
return await this.todoRepository.create(obj);
@post('/todos', {
responses: {
'200': {
description: 'Todo model instance',
content: {'application/json': {'x-ts-type': Todo}},
},
},
})
async create(@requestBody() data: Todo): Promise<Todo> {
return await this.todoRepository.create(data);
}

@get('/todos/count')
async count(@param.query.string('where') where?: Where): Promise<number> {
@get('/todos/count', {
responses: {
'200': {
description: 'Todo model count',
content: {'application/json': {'x-ts-type': Number}},
},
},
})
async count(
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where,
): Promise<number> {
return await this.todoRepository.count(where);
}

@get('/todos')
async find(@param.query.string('filter') filter?: Filter): Promise<Todo[]> {
@get('/todos', {
responses: {
'200': {
description: 'Array of Todo model instances',
content: {
'application/json': {
schema: {type: 'array', items: {'x-ts-type': Todo}},
},
},
},
},
})
async find(
@param.query.object('filter', getFilterSchemaFor(Todo)) filter?: Filter,
): Promise<Todo[]> {
return await this.todoRepository.find(filter);
}

@patch('/todos')
@patch('/todos', {
responses: {
'200': {
description: 'Todo PATCH success count',
content: {'application/json': {'x-ts-type': Number}},
},
},
})
async updateAll(
@requestBody() obj: Todo,
@param.query.string('where') where?: Where,
@requestBody() data: Todo,
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where,
): Promise<number> {
return await this.todoRepository.updateAll(obj, where);
return await this.todoRepository.updateAll(data, where);
}

@get('/todos/{id}')
@get('/todos/{id}', {
responses: {
'200': {
description: 'Todo model instance',
content: {'application/json': {'x-ts-type': Todo}},
},
},
})
async findById(@param.path.number('id') id: number): Promise<Todo> {
return await this.todoRepository.findById(id);
}

@patch('/todos/{id}')
@patch('/todos/{id}', {
responses: {
'204': {
description: 'Todo PATCH success',
},
},
})
async updateById(
@param.path.number('id') id: number,
@requestBody() obj: Todo,
@requestBody() data: Todo,
): Promise<void> {
await this.todoRepository.updateById(id, obj);
await this.todoRepository.updateById(id, data);
}

@del('/todos/{id}')
@del('/todos/{id}', {
responses: {
'204': {
description: 'Todo DELETE success',
},
},
})
async deleteById(@param.path.number('id') id: number): Promise<void> {
await this.todoRepository.deleteById(id);
}
Expand Down
124 changes: 98 additions & 26 deletions docs/site/todo-list-tutorial-controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,47 +98,119 @@ Using our constraining factory as we did with the `POST` request, we'll define
the controller methods for the rest of the HTTP verbs for the route. The
completed controller should look as follows:

#### src/controllers/todo-list-todo.controller.ts
#### src/controllers/todo-list.controller.ts

```ts
import {repository, Filter, Where} from '@loopback/repository';
import {Filter, repository, Where} from '@loopback/repository';
import {
del,
get,
getFilterSchemaFor,
getWhereSchemaFor,
param,
patch,
post,
requestBody,
} from '@loopback/rest';
import {TodoList} from '../models';
import {TodoListRepository} from '../repositories';
import {post, get, patch, del, param, requestBody} from '@loopback/rest';
import {Todo} from '../models';

export class TodoListTodoController {
export class TodoListController {
constructor(
@repository(TodoListRepository) protected todoListRepo: TodoListRepository,
@repository(TodoListRepository)
public todoListRepository: TodoListRepository,
) {}

@post('/todo-lists/{id}/todos')
async create(@param.path.number('id') id: number, @requestBody() todo: Todo) {
return await this.todoListRepo.todos(id).create(todo);
@post('/todo-lists', {
responses: {
'200': {
description: 'TodoList model instance',
content: {'application/json': {'x-ts-type': TodoList}},
},
},
})
async create(@requestBody() obj: TodoList): Promise<TodoList> {
return await this.todoListRepository.create(obj);
}

@get('/todo-lists/{id}/todos')
@get('/todo-lists/count', {
responses: {
'200': {
description: 'TodoList model count',
content: {'application/json': {'x-ts-type': Number}},
},
},
})
async count(
@param.query.object('where', getWhereSchemaFor(TodoList)) where?: Where,
): Promise<number> {
return await this.todoListRepository.count(where);
}

@get('/todo-lists', {
responses: {
'200': {
description: 'Array of TodoList model instances',
content: {'application/json': {'x-ts-type': TodoList}},
},
},
})
async find(
@param.path.number('id') id: number,
@param.query.string('filter') filter?: Filter,
) {
return await this.todoListRepo.todos(id).find(filter);
@param.query.object('filter', getFilterSchemaFor(TodoList)) filter?: Filter,
): Promise<TodoList[]> {
return await this.todoListRepository.find(filter);
}

@patch('/todo-lists/{id}/todos')
async patch(
@param.path.number('id') id: number,
@requestBody() todo: Partial<Todo>,
@param.query.string('where') where?: Where,
) {
return await this.todoListRepo.todos(id).patch(todo, where);
@patch('/todo-lists', {
responses: {
'200': {
description: 'TodoList PATCH success count',
content: {'application/json': {'x-ts-type': Number}},
},
},
})
async updateAll(
@requestBody() obj: Partial<TodoList>,
@param.query.object('where', getWhereSchemaFor(TodoList)) where?: Where,
): Promise<number> {
return await this.todoListRepository.updateAll(obj, where);
}

@del('/todo-lists/{id}/todos')
async delete(
@get('/todo-lists/{id}', {
responses: {
'200': {
description: 'TodoList model instance',
content: {'application/json': {'x-ts-type': TodoList}},
},
},
})
async findById(@param.path.number('id') id: number): Promise<TodoList> {
return await this.todoListRepository.findById(id);
}

@patch('/todo-lists/{id}', {
responses: {
'204': {
description: 'TodoList PATCH success',
},
},
})
async updateById(
@param.path.number('id') id: number,
@param.query.string('where') where?: Where,
) {
return await this.todoListRepo.todos(id).delete(where);
@requestBody() obj: TodoList,
): Promise<void> {
await this.todoListRepository.updateById(id, obj);
}

@del('/todo-lists/{id}', {
responses: {
'204': {
description: 'TodoList DELETE success',
},
},
})
async deleteById(@param.path.number('id') id: number): Promise<void> {
await this.todoListRepository.deleteById(id);
}
}
```
Expand Down
18 changes: 13 additions & 5 deletions examples/todo-list/src/controllers/todo-list-todo.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {repository, Filter, Where} from '@loopback/repository';
import {TodoListRepository} from '../repositories';
import {post, get, patch, del, param, requestBody} from '@loopback/rest';
import {Filter, repository, Where} from '@loopback/repository';
import {
del,
get,
getWhereSchemaFor,
param,
patch,
post,
requestBody,
} from '@loopback/rest';
import {Todo} from '../models';
import {TodoListRepository} from '../repositories';

export class TodoListTodoController {
constructor(
Expand Down Expand Up @@ -58,7 +66,7 @@ export class TodoListTodoController {
async patch(
@param.path.number('id') id: number,
@requestBody() todo: Partial<Todo>,
@param.query.string('where') where?: Where,
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where,
): Promise<number> {
return await this.todoListRepo.todos(id).patch(todo, where);
}
Expand All @@ -73,7 +81,7 @@ export class TodoListTodoController {
})
async delete(
@param.path.number('id') id: number,
@param.query.string('where') where?: Where,
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where,
): Promise<number> {
return await this.todoListRepo.todos(id).delete(where);
}
Expand Down
19 changes: 15 additions & 4 deletions examples/todo-list/src/controllers/todo-list.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@
// License text available at https://opensource.org/licenses/MIT

import {Filter, repository, Where} from '@loopback/repository';
import {del, get, param, patch, post, requestBody} from '@loopback/rest';
import {
del,
get,
getFilterSchemaFor,
getWhereSchemaFor,
param,
patch,
post,
requestBody,
} from '@loopback/rest';
import {TodoList} from '../models';
import {TodoListRepository} from '../repositories';

Expand Down Expand Up @@ -34,7 +43,9 @@ export class TodoListController {
},
},
})
async count(@param.query.string('where') where?: Where): Promise<number> {
async count(
@param.query.object('where', getWhereSchemaFor(TodoList)) where?: Where,
): Promise<number> {
return await this.todoListRepository.count(where);
}

Expand All @@ -47,7 +58,7 @@ export class TodoListController {
},
})
async find(
@param.query.string('filter') filter?: Filter,
@param.query.object('filter', getFilterSchemaFor(TodoList)) filter?: Filter,
): Promise<TodoList[]> {
return await this.todoListRepository.find(filter);
}
Expand All @@ -62,7 +73,7 @@ export class TodoListController {
})
async updateAll(
@requestBody() obj: Partial<TodoList>,
@param.query.string('where') where?: Where,
@param.query.object('where', getWhereSchemaFor(TodoList)) where?: Where,
): Promise<number> {
return await this.todoListRepository.updateAll(obj, where);
}
Expand Down
Loading

0 comments on commit 7e1acfc

Please sign in to comment.