Skip to content

Commit

Permalink
Merge pull request #15 from hpi-schul-cloud/arch-meeting/add-api-resp…
Browse files Browse the repository at this point in the history
…onse-design

Arch meeting/add api response design
  • Loading branch information
wolfganggreschus authored Nov 2, 2023
2 parents c640e2f + 6669b61 commit d5f6976
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

/.vscode
69 changes: 69 additions & 0 deletions docs/schulcloud-server/Api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# API design

## nest.js

In nest.js all apis are defined in controllers.
Usually the api follows the following syntax:

```typescript
/api/v3/<resource>
```

- Each controller is responsible for a specific resource.
- The controller is responsible for the routing and the validation of the request.
- The controller calls a service to handle the request.
- The service is responsible for the business logic.
- The service calls a repository to access the database.
- The repository is responsible for the database access.

## Responses

When returning a response like this:

```typescript
@ApiOperation({ summary: 'Create a new element on a card.' })
@ApiExtraModels(
ExternalToolElementResponse,
FileElementResponse,
LinkElementResponse,
RichTextElementResponse,
SubmissionContainerElementResponse
)
@ApiResponse({
status: 201,
schema: {
oneOf: [
{ $ref: getSchemaPath(ExternalToolElementResponse) },
{ $ref: getSchemaPath(FileElementResponse) },
{ $ref: getSchemaPath(LinkElementResponse) },
{ $ref: getSchemaPath(RichTextElementResponse) },
{ $ref: getSchemaPath(SubmissionContainerElementResponse) },
],
},
})
@ApiResponse({ status: 400, type: ApiValidationError })
@ApiResponse({ status: 403, type: ForbiddenException })
@ApiResponse({ status: 404, type: NotFoundException })
@Post(':cardId/elements')
async createElement(
@Param() urlParams: CardUrlParams,
@Body() bodyParams: CreateContentElementBodyParams,
@CurrentUser() currentUser: ICurrentUser
): Promise<AnyContentElementResponse> {
const { type, toPosition } = bodyParams;
const element = await this.cardUc.createElement(currentUser.userId, urlParams.cardId, type, toPosition);
const response = ContentElementResponseFactory.mapToResponse(element);

return response;
}
```

We want to use decorators to explain the intent of the response.
The `@ApiOperation` decorator is used to define the summary.
The `@ApiResponse` decorator is used to define the response.
The `@ApiExtraModels` decorator is used to define the response models.

The final response should either be an javascript Object or an array.
We do not return primitives like `string` or `boolean`.

Swagger will automatically generate the response schema from the response object.
1 change: 1 addition & 0 deletions static/CNAME
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
documentation.dbildungscloud.dev

0 comments on commit d5f6976

Please sign in to comment.