Skip to content

Commit 7e1acfc

Browse files
committed
feat: add "filter" parameter to "find" endpoints
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.
1 parent ca8d96e commit 7e1acfc

File tree

15 files changed

+417
-94
lines changed

15 files changed

+417
-94
lines changed

docs/site/Controller-generator.md

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,17 @@ Here's an example of what the template will produce given a `Todo` model and a
9696
`TodoRepository`:
9797

9898
```ts
99-
import {Filter, Where, repository} from '@loopback/repository';
100-
import {post, param, get, patch, del, requestBody} from '@loopback/rest';
99+
import {Filter, repository, Where} from '@loopback/repository';
100+
import {
101+
post,
102+
param,
103+
get,
104+
getFilterSchemaFor,
105+
getWhereSchemaFor,
106+
patch,
107+
del,
108+
requestBody,
109+
} from '@loopback/rest';
101110
import {Todo} from '../models';
102111
import {TodoRepository} from '../repositories';
103112

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

109-
@post('/todos')
110-
async create(@requestBody() obj: Todo): Promise<Todo> {
111-
return await this.todoRepository.create(obj);
118+
@post('/todos', {
119+
responses: {
120+
'200': {
121+
description: 'Todo model instance',
122+
content: {'application/json': {'x-ts-type': Todo}},
123+
},
124+
},
125+
})
126+
async create(@requestBody() data: Todo): Promise<Todo> {
127+
return await this.todoRepository.create(data);
112128
}
113129

114-
@get('/todos/count')
115-
async count(@param.query.string('where') where?: Where): Promise<number> {
130+
@get('/todos/count', {
131+
responses: {
132+
'200': {
133+
description: 'Todo model count',
134+
content: {'application/json': {'x-ts-type': Number}},
135+
},
136+
},
137+
})
138+
async count(
139+
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where,
140+
): Promise<number> {
116141
return await this.todoRepository.count(where);
117142
}
118143

119-
@get('/todos')
120-
async find(@param.query.string('filter') filter?: Filter): Promise<Todo[]> {
144+
@get('/todos', {
145+
responses: {
146+
'200': {
147+
description: 'Array of Todo model instances',
148+
content: {
149+
'application/json': {
150+
schema: {type: 'array', items: {'x-ts-type': Todo}},
151+
},
152+
},
153+
},
154+
},
155+
})
156+
async find(
157+
@param.query.object('filter', getFilterSchemaFor(Todo)) filter?: Filter,
158+
): Promise<Todo[]> {
121159
return await this.todoRepository.find(filter);
122160
}
123161

124-
@patch('/todos')
162+
@patch('/todos', {
163+
responses: {
164+
'200': {
165+
description: 'Todo PATCH success count',
166+
content: {'application/json': {'x-ts-type': Number}},
167+
},
168+
},
169+
})
125170
async updateAll(
126-
@requestBody() obj: Todo,
127-
@param.query.string('where') where?: Where,
171+
@requestBody() data: Todo,
172+
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where,
128173
): Promise<number> {
129-
return await this.todoRepository.updateAll(obj, where);
174+
return await this.todoRepository.updateAll(data, where);
130175
}
131176

132-
@get('/todos/{id}')
177+
@get('/todos/{id}', {
178+
responses: {
179+
'200': {
180+
description: 'Todo model instance',
181+
content: {'application/json': {'x-ts-type': Todo}},
182+
},
183+
},
184+
})
133185
async findById(@param.path.number('id') id: number): Promise<Todo> {
134186
return await this.todoRepository.findById(id);
135187
}
136188

137-
@patch('/todos/{id}')
189+
@patch('/todos/{id}', {
190+
responses: {
191+
'204': {
192+
description: 'Todo PATCH success',
193+
},
194+
},
195+
})
138196
async updateById(
139197
@param.path.number('id') id: number,
140-
@requestBody() obj: Todo,
198+
@requestBody() data: Todo,
141199
): Promise<void> {
142-
await this.todoRepository.updateById(id, obj);
200+
await this.todoRepository.updateById(id, data);
143201
}
144202

145-
@del('/todos/{id}')
203+
@del('/todos/{id}', {
204+
responses: {
205+
'204': {
206+
description: 'Todo DELETE success',
207+
},
208+
},
209+
})
146210
async deleteById(@param.path.number('id') id: number): Promise<void> {
147211
await this.todoRepository.deleteById(id);
148212
}

docs/site/todo-list-tutorial-controller.md

Lines changed: 98 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -98,47 +98,119 @@ Using our constraining factory as we did with the `POST` request, we'll define
9898
the controller methods for the rest of the HTTP verbs for the route. The
9999
completed controller should look as follows:
100100

101-
#### src/controllers/todo-list-todo.controller.ts
101+
#### src/controllers/todo-list.controller.ts
102102

103103
```ts
104-
import {repository, Filter, Where} from '@loopback/repository';
104+
import {Filter, repository, Where} from '@loopback/repository';
105+
import {
106+
del,
107+
get,
108+
getFilterSchemaFor,
109+
getWhereSchemaFor,
110+
param,
111+
patch,
112+
post,
113+
requestBody,
114+
} from '@loopback/rest';
115+
import {TodoList} from '../models';
105116
import {TodoListRepository} from '../repositories';
106-
import {post, get, patch, del, param, requestBody} from '@loopback/rest';
107-
import {Todo} from '../models';
108117

109-
export class TodoListTodoController {
118+
export class TodoListController {
110119
constructor(
111-
@repository(TodoListRepository) protected todoListRepo: TodoListRepository,
120+
@repository(TodoListRepository)
121+
public todoListRepository: TodoListRepository,
112122
) {}
113123

114-
@post('/todo-lists/{id}/todos')
115-
async create(@param.path.number('id') id: number, @requestBody() todo: Todo) {
116-
return await this.todoListRepo.todos(id).create(todo);
124+
@post('/todo-lists', {
125+
responses: {
126+
'200': {
127+
description: 'TodoList model instance',
128+
content: {'application/json': {'x-ts-type': TodoList}},
129+
},
130+
},
131+
})
132+
async create(@requestBody() obj: TodoList): Promise<TodoList> {
133+
return await this.todoListRepository.create(obj);
117134
}
118135

119-
@get('/todo-lists/{id}/todos')
136+
@get('/todo-lists/count', {
137+
responses: {
138+
'200': {
139+
description: 'TodoList model count',
140+
content: {'application/json': {'x-ts-type': Number}},
141+
},
142+
},
143+
})
144+
async count(
145+
@param.query.object('where', getWhereSchemaFor(TodoList)) where?: Where,
146+
): Promise<number> {
147+
return await this.todoListRepository.count(where);
148+
}
149+
150+
@get('/todo-lists', {
151+
responses: {
152+
'200': {
153+
description: 'Array of TodoList model instances',
154+
content: {'application/json': {'x-ts-type': TodoList}},
155+
},
156+
},
157+
})
120158
async find(
121-
@param.path.number('id') id: number,
122-
@param.query.string('filter') filter?: Filter,
123-
) {
124-
return await this.todoListRepo.todos(id).find(filter);
159+
@param.query.object('filter', getFilterSchemaFor(TodoList)) filter?: Filter,
160+
): Promise<TodoList[]> {
161+
return await this.todoListRepository.find(filter);
125162
}
126163

127-
@patch('/todo-lists/{id}/todos')
128-
async patch(
129-
@param.path.number('id') id: number,
130-
@requestBody() todo: Partial<Todo>,
131-
@param.query.string('where') where?: Where,
132-
) {
133-
return await this.todoListRepo.todos(id).patch(todo, where);
164+
@patch('/todo-lists', {
165+
responses: {
166+
'200': {
167+
description: 'TodoList PATCH success count',
168+
content: {'application/json': {'x-ts-type': Number}},
169+
},
170+
},
171+
})
172+
async updateAll(
173+
@requestBody() obj: Partial<TodoList>,
174+
@param.query.object('where', getWhereSchemaFor(TodoList)) where?: Where,
175+
): Promise<number> {
176+
return await this.todoListRepository.updateAll(obj, where);
134177
}
135178

136-
@del('/todo-lists/{id}/todos')
137-
async delete(
179+
@get('/todo-lists/{id}', {
180+
responses: {
181+
'200': {
182+
description: 'TodoList model instance',
183+
content: {'application/json': {'x-ts-type': TodoList}},
184+
},
185+
},
186+
})
187+
async findById(@param.path.number('id') id: number): Promise<TodoList> {
188+
return await this.todoListRepository.findById(id);
189+
}
190+
191+
@patch('/todo-lists/{id}', {
192+
responses: {
193+
'204': {
194+
description: 'TodoList PATCH success',
195+
},
196+
},
197+
})
198+
async updateById(
138199
@param.path.number('id') id: number,
139-
@param.query.string('where') where?: Where,
140-
) {
141-
return await this.todoListRepo.todos(id).delete(where);
200+
@requestBody() obj: TodoList,
201+
): Promise<void> {
202+
await this.todoListRepository.updateById(id, obj);
203+
}
204+
205+
@del('/todo-lists/{id}', {
206+
responses: {
207+
'204': {
208+
description: 'TodoList DELETE success',
209+
},
210+
},
211+
})
212+
async deleteById(@param.path.number('id') id: number): Promise<void> {
213+
await this.todoListRepository.deleteById(id);
142214
}
143215
}
144216
```

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,18 @@
33
// This file is licensed under the MIT License.
44
// License text available at https://opensource.org/licenses/MIT
55

6-
import {repository, Filter, Where} from '@loopback/repository';
7-
import {TodoListRepository} from '../repositories';
8-
import {post, get, patch, del, param, requestBody} from '@loopback/rest';
6+
import {Filter, repository, Where} from '@loopback/repository';
7+
import {
8+
del,
9+
get,
10+
getWhereSchemaFor,
11+
param,
12+
patch,
13+
post,
14+
requestBody,
15+
} from '@loopback/rest';
916
import {Todo} from '../models';
17+
import {TodoListRepository} from '../repositories';
1018

1119
export class TodoListTodoController {
1220
constructor(
@@ -58,7 +66,7 @@ export class TodoListTodoController {
5866
async patch(
5967
@param.path.number('id') id: number,
6068
@requestBody() todo: Partial<Todo>,
61-
@param.query.string('where') where?: Where,
69+
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where,
6270
): Promise<number> {
6371
return await this.todoListRepo.todos(id).patch(todo, where);
6472
}
@@ -73,7 +81,7 @@ export class TodoListTodoController {
7381
})
7482
async delete(
7583
@param.path.number('id') id: number,
76-
@param.query.string('where') where?: Where,
84+
@param.query.object('where', getWhereSchemaFor(Todo)) where?: Where,
7785
): Promise<number> {
7886
return await this.todoListRepo.todos(id).delete(where);
7987
}

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@
44
// License text available at https://opensource.org/licenses/MIT
55

66
import {Filter, repository, Where} from '@loopback/repository';
7-
import {del, get, param, patch, post, requestBody} from '@loopback/rest';
7+
import {
8+
del,
9+
get,
10+
getFilterSchemaFor,
11+
getWhereSchemaFor,
12+
param,
13+
patch,
14+
post,
15+
requestBody,
16+
} from '@loopback/rest';
817
import {TodoList} from '../models';
918
import {TodoListRepository} from '../repositories';
1019

@@ -34,7 +43,9 @@ export class TodoListController {
3443
},
3544
},
3645
})
37-
async count(@param.query.string('where') where?: Where): Promise<number> {
46+
async count(
47+
@param.query.object('where', getWhereSchemaFor(TodoList)) where?: Where,
48+
): Promise<number> {
3849
return await this.todoListRepository.count(where);
3950
}
4051

@@ -47,7 +58,7 @@ export class TodoListController {
4758
},
4859
})
4960
async find(
50-
@param.query.string('filter') filter?: Filter,
61+
@param.query.object('filter', getFilterSchemaFor(TodoList)) filter?: Filter,
5162
): Promise<TodoList[]> {
5263
return await this.todoListRepository.find(filter);
5364
}
@@ -62,7 +73,7 @@ export class TodoListController {
6273
})
6374
async updateAll(
6475
@requestBody() obj: Partial<TodoList>,
65-
@param.query.string('where') where?: Where,
76+
@param.query.object('where', getWhereSchemaFor(TodoList)) where?: Where,
6677
): Promise<number> {
6778
return await this.todoListRepository.updateAll(obj, where);
6879
}

0 commit comments

Comments
 (0)