Skip to content

Commit

Permalink
Issue 30 (#33)
Browse files Browse the repository at this point in the history
* @Header decorator + tests

* Doc for @Header() decorator

* Header decorator returns null if no header on request

* doc fix

* fix?

* style

* style(*):  double quote to quote

* style(*):  add semicolon at end of lines

Co-authored-by: Jacob Gaudreau <jacob.gaudreau@umontreal.ca>
  • Loading branch information
Sorikairox and Jacob Gaudreau committed Jun 2, 2022
1 parent c3b0b4f commit 8ff42e0
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 113 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<img src="https://user-images.githubusercontent.com/38007824/170542778-5ffe8414-38ea-438e-a02b-15a7c4800252.png" width="250" alt="Danet Logo" />
</p>


[![CI](https://github.com/Sorikairox/Danet/actions/workflows/run-tests.yml/badge.svg)](https://github.com/Sorikairox/Danet/actions/workflows/run-tests.yml)
[![codecov](https://codecov.io/gh/Sorikairox/Danet/branch/main/graph/badge.svg?token=R6WXVC669Z)](https://codecov.io/gh/Sorikairox/Danet)

Expand Down
22 changes: 17 additions & 5 deletions doc/first-steps/controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,16 @@ objects they represent.
<td><code>@Req()</code></td>
<td><code>ctx.request</code></td></tr>
<tr>
<td><code>@Res()</code><span class="table-code-asterisk">*</span></td>
<td><code>@Res()</code><span class='table-code-asterisk'>*</span></td>
<td><code>ctx.response</code></td>
</tr>
<tr>
<td><code>@Param(key: string)</code></td>
<td><code>getQuery(context, { mergeParams: true })[key]</code></td>
</tr>
<tr>
<td><code>@Header(key? : string)</code></td>
<td><code>ctx.request.headers</code> / <code>ctx.request.headers.get(key)</code></td></tr>
<tr>
<td><code>@Body(key?: string)</code></td>
<td><code>ctx.request.body</code> / <code>ctx.request.body[key]</code></td>
Expand Down Expand Up @@ -153,7 +156,7 @@ findOne(@Param('id') id: string): string {
`@Param()` is used to decorate a method parameter by giving a particular
parameter token to the decorator.

!!!info Hint
!!!info Hint
Import `Param` from the `https://deno.land/x/danet/mod.ts` package.
!!!

Expand All @@ -174,7 +177,7 @@ Being a modern framework, we know that data extraction is mostly
**asynchronous**. That's why Danet supports and works well with `async`
functions.

!!!info Hint
!!!info Hint
Learn more about `async / await` feature [here](https://kamilmysliwiec.com/typescript-2-1-introduction-async-await)
!!!

Expand All @@ -201,7 +204,16 @@ create a basic controller. This controller exposes a couple of methods to access
and manipulate internal data.

```ts cats.controller.ts
import { Controller, Get, Query, Post, Body, Put, Param, Delete } from 'https://deno.land/x/danet/mod.ts';
import {
Controller,
Get,
Query,
Post,
Body,
Put,
Param,
Delete,
} from 'https://deno.land/x/danet/mod.ts';
import { CreateCatDto, UpdateCatDto, ListAllEntities } from './dto';
@Controller('cats')
Expand All @@ -210,7 +222,7 @@ export class CatsController {
create(@Body() createCatDto: CreateCatDto) {
return 'This action adds a new cat';
}
@Get(':id')
findOne(@Param('id') id: string) {
return `This action returns a #${id} cat`;
Expand Down
49 changes: 26 additions & 23 deletions doc/first-steps/exception-filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ filter generates the following default JSON response:

```json
{
"statusCode": 500,
"message": "Internal server error!"
"statusCode": 500,
"message": "Internal server error!"
}
```

!!!info **Hint**
!!!info **Hint**
Any thrown exception containing the `statusCode` and `message`
property will be properly populated and send back as a response (instead of the
default `InternalServerError` for unrecognized exceptions).
Expand Down Expand Up @@ -61,7 +61,11 @@ which are an instance of the `CustomException` class, and implementing custom
response logic for them.

```ts custom-exception.filter.ts
import { ExceptionFilter, Catch, HttpContext } from 'https://deno.land/x/danet/mod.ts';
import {
ExceptionFilter,
Catch,
HttpContext,
} from 'https://deno.land/x/danet/mod.ts';

@Catch(CustomException)
export class CustomExceptionFilter implements ExceptionFilter {
Expand All @@ -75,7 +79,7 @@ export class CustomExceptionFilter implements ExceptionFilter {
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
}
};
}
}
```
Expand Down Expand Up @@ -123,25 +127,24 @@ type), omit `@Catch()` decorator.

```typescript
import {
Catch,
ExceptionFilter,
HttpContext,
Catch,
ExceptionFilter,
HttpContext,
} from 'https://deno.land/x/danet/mod.ts';
export class AllExceptionsFilter implements ExceptionFilter {
constructor() {
}

catch(exception: unknown, ctx: HttpContext): boolean {
const response = ctx.response;
const request = ctx.request;
const status = exception.status;

response.status = status;
response.body = {
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
};
}
constructor() {}

catch(exception: unknown, ctx: HttpContext): boolean {
const response = ctx.response;
const request = ctx.request;
const status = exception.status;

response.status = status;
response.body = {
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
};
}
}
```
17 changes: 9 additions & 8 deletions doc/first-steps/renderer.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ engine.
/views/partials
```

!!!info Info
!!!info Info
If you want to put these directory elsewhere, you can provide the
path to `views` at runtime with `app.setViewEngineDir('my/path/to/views);`
!!!
Expand All @@ -36,10 +36,11 @@ directory. It will print 2 variables passed from your controller.
<html>
<head>
<meta charset="utf-8" />
<title>{{ title }}</title>
<title>{{title}}</title>
</head>
<body>
Hello {{ name }}!
Hello
{{name}}!
</body>
</html>
```
Expand All @@ -49,11 +50,11 @@ Now, let's tell your controller it has to render this view on a specific route:
```ts
@Controller('nice-controller')
class MyController {
@Render('hello')
@Get('/')
renderANiceHTML() {
return { title: 'the page title', name: 'world' };
}
@Render('hello')
@Get('/')
renderANiceHTML() {
return { title: "the page title", name: "world" };
}
}
```

Expand Down
56 changes: 56 additions & 0 deletions spec/method-param-decorator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Module } from '../src/module/decorator.ts';
import { Controller, Get, Post } from '../src/router/controller/decorator.ts';
import {
Body,
Header,
Param,
Query,
Res,
Expand All @@ -17,6 +18,18 @@ class SimpleController {
return myvalue;
}

@Get('/lambda')
headerParamWithAttribute(@Header('Accept-Language') acceptHeader: string) {
if (!acceptHeader) return 'No "Accept-Language" header';
return acceptHeader;
}

@Post('/lambda')
headerParamWithoutAttribute(@Header() headers: Headers) {
if (!headers) return 'null';
return headers instanceof Headers;
}

@Post('/')
bodyParamWithAttribute(@Body('whatisit') niceValue: string) {
return niceValue;
Expand Down Expand Up @@ -52,6 +65,49 @@ Deno.test('@Res and @Query decorator', async () => {
await app.close();
});

Deno.test('@Header decorator with attribute', async () => {
await app.init(MyModule);
const port = (await app.listen(0)).port;

const res = await fetch(`http://localhost:${port}/lambda`, {
method: 'GET',
headers: {
'Accept-Language': 'en-US',
},
});
const text = await res.text();
assertEquals(text, 'en-US');
await app.close();
});

Deno.test('@Header decorator without attribute', async () => {
await app.init(MyModule);
const port = (await app.listen(0)).port;

const res = await fetch(`http://localhost:${port}/lambda`, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
});
const text = await res.text();
assertEquals(text, 'true');
await app.close();
});

Deno.test('@Header decorator with attribute without qualifying header on request', async () => {
await app.init(MyModule);
const port = (await app.listen(0)).port;

const res = await fetch(`http://localhost:${port}/lambda`, {
method: 'GET',
headers: {},
});
const text = await res.text();
assertEquals(text, 'No "Accept-Language" header');
await app.close();
});

Deno.test('@Body decorator with attribute', async () => {
await app.init(MyModule);
const port = (await app.listen(0)).port;
Expand Down
Loading

0 comments on commit 8ff42e0

Please sign in to comment.