Skip to content

Commit

Permalink
Merge pull request #40 from francescovallone/develop
Browse files Browse the repository at this point in the history
chore: prepare for release 0.5
  • Loading branch information
francescovallone authored Jun 26, 2024
2 parents 962466b + be1f82e commit edfb04b
Show file tree
Hide file tree
Showing 73 changed files with 1,498 additions and 886 deletions.
14 changes: 13 additions & 1 deletion .website/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default defineConfig({
{ text: 'Middlewares', link: 'middlewares' },
{ text: 'WebSockets', link: 'websockets' },
{ text: 'Hooks', link: 'hooks' },
{ text: 'Shelf Interoperability', link: 'shelf_interop' }
]
},
{
Expand All @@ -70,8 +71,19 @@ export default defineConfig({
{ text: 'Serve Static Files', link: 'serve_static' },
{ text: 'CORS', link: 'cors' },
{ text: 'Rate Limiter', link: 'rate_limiter' },
{
text: 'Swagger',
collapsed: true,
base: '/plugins/swagger/',
items: [
{ text: 'Introduction', link: '/' },
{ text: 'Document', link: 'document' },
{ text: 'Api Specification', link: 'api_spec' },
{ text: 'Components', link: 'components' },
],
},
{ text: 'Health Check [WIP]' },
{ text: 'Cron [WIP]' },
{ text: 'Swagger [WIP]' }
],
link: '/'
},
Expand Down
4 changes: 2 additions & 2 deletions .website/components/fast.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const graphs = [
</script>

<template>
<div class="container flex w-full gap-8 flex-row my-8">
<div class="container flex w-full gap-8 lg:flex-row flex-col my-8">
<section class="flex flex-col gap-6 flex-1">
<h1 class="text-2xl font-bold">Fast 🚀</h1>
<p class="text-xl text-gray-400">
Expand Down Expand Up @@ -108,7 +108,7 @@ const graphs = [

<style scoped>
p {
margin: 0;
margin: 0 !important;
}
.results{
line-height: 1rem;
Expand Down
2 changes: 1 addition & 1 deletion .website/components/modular.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const plugins = [

<template>
<div class="container flex w-full gap-8 flex-col my-8">
<div class="container flex w-full gap-8 flex-row">
<div class="container flex w-full gap-8 flex-col lg:flex-row">
<section class="flex flex-col gap-6 flex-1">
<h1 class="text-2xl font-bold">Modular 📦</h1>
<p class="text-xl text-gray-400">
Expand Down
37 changes: 13 additions & 24 deletions .website/deployment/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,24 @@

Serinus can be run in a Docker container and the creation of the Dockerfile is automated by the `serinus` command line tool.

We can use the following code for the Dockerfile:
To create a Dockerfile for your Serinus application, run the following command:

```dockerfile
FROM dart:latest AS build


WORKDIR /app

COPY . ./
COPY pubspec.* ./
RUN dart pub get
COPY . .

RUN dart pub get --offline
RUN dart compile exe bin/${ENTRYPOINT}.dart -o bin/${OUTPUT}

FROM scratch
EXPOSE ${PORT}
COPY --from=build /runtime/ /
COPY --from=build /app/bin/${OUTPUT} /app/bin/

CMD ["/app/bin/${OUTPUT}"]
```bash
serinus deploy
```

To use it we need to replace `${ENTRYPOINT}` with the name of the entrypoint file and `${OUTPUT}` with the name of the output file and `${PORT}` with the port that the application will run on.
The deploy command has the following options:

- `--port`: The port to expose the application on. Default is `3000`.
- `--output`: The output file for the application. Default is `app`.

Perfect! We are set to build the image and run the container on our server.
## Build and Run the Docker Image

```bash
docker build -t myapp .
docker run -d -p 8080:8080 myapp
docker run -d -p 3000:3000 myapp
```

This will build the Docker image and run the container on port `3000`.

And that's it! Your Serinus application is now running in a Docker container.
2 changes: 1 addition & 1 deletion .website/deployment/globe.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ globe deploy

When prompted to enter the path to your entrypoint file, enter the path to your entrypoint file in your project. If you use the serinus cli to create your project, the entrypoint file will be located in the `bin` directory.

This will deploy your application to the Globe service and provide you with a URL to access your application.
This will deploy your application to the Globe service and provide you with a URL to access your application.
8 changes: 8 additions & 0 deletions .website/overview/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,11 @@ serinus run
```

Your applications is now running and listening for requests on port 3000.

### Using the CLI tool

If you are using the CLI tool, then there are some interesting options to run the application:

- `--port`: The port to expose the application on. Default is `3000`.
- `--host`: The host to expose the application on. Default is `localhost`.
- `--dev`: Flag to run the application in development mode. If this flag is set, the application will be reloaded every time a file is changed.
4 changes: 3 additions & 1 deletion .website/overview/middlewares.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ The `use` method must return the next function, otherwise the request will not b
To use a middleware, you need to add it to the `middlewares` list in your module.

::: code-group

```dart [my_middleware.dart]
import 'package:serinus/serinus.dart';
Expand All @@ -51,6 +52,7 @@ class MyModule extends Module {
);
}
```

:::

Doing this will make the middleware available to all controllers and routes in the module and its submodules.
Expand All @@ -71,4 +73,4 @@ class MyMiddleware extends Middleware {
}
```

This will make the middleware only be applied to the routes that match the pattern `/`.
This will make the middleware only be applied to the routes that match the pattern `/`.
49 changes: 32 additions & 17 deletions .website/overview/routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ They only exposes the endpoint and the method that the route will respond to so

## Create a route

To add routes you can either create a class that extends the `Route` class or use the following methods to create one.
To add routes you can either create a class that extends the `Route` class or use the following methods to create one.

- `Route.get`
- `Route.post`
Expand Down Expand Up @@ -127,37 +127,52 @@ class GetRoute extends Route {
});
@override
Future<RequestContext> transform(RequestContext context) async {
return context;
Future<void> transform(RequestContext context) async {
return;
}
}
```

## Parsing (and validate) the RequestContext
## Parsing (and validate) the request

You can parse the `RequestContext` before it reaches the route handler by overriding the `parse` method.
You can parse some of the `Request` properties before they reach the route handler by creating a ParseSchema.
Serinus follows the [Parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/) principle, so if the parsing fails, the request is not valid and should be rejected.

```dart
import 'package:serinus/serinus.dart';
class GetRoute extends Route {
const GetRoute({
required super.path,
super.method = HttpMethod.get,
});
@override
Future<RequestContext> parse(RequestContext context) async {
return context;
}
class AppController extends Controller {
AppController({super.path = '/'}) {
on(
Route.get('/'),
(context) {
return Response.text('Hello World!');
},
ParseSchema(
query: object({
'name': string().minLength(3),
})
),
);
}
}
```

::: info
If you need an amazing validation library you can try [Acanthis](https://pub.dev/packages/acanthis). 🐤
Serinus uses [Acanthis](https://pub.dev/packages/acanthis) under the hood to take care of the parse and validate process. 🐤
:::

The `ParseSchema` class has the following properties:

- `query`: A schema that will be used to parse the query parameters.
- `body`: A schema that will be used to parse the body of the request.
- `headers`: A schema that will be used to parse the headers of the request.
- `session`: A schema that will be used to parse the cookies of the request.
- `params`: A schema that will be used to parse the path parameters of the request.
- `error`: Custom exception that will be returned if the parsing fails.

All the schemas are optional and you can use them in any combination and the `body` schema is not an object schema, so you can use any schema that you want.

## Manage what happens before and after the route

You can manage what happens before and after the route is executed by overriding the `beforeHandle` and `afterHandle` methods.
Expand All @@ -183,4 +198,4 @@ class GetRoute extends Route {
}
```

These two methods are actually local hooks. You can check when they will be executed in the [Request Lifecycle](../request_lifecycle) section.
These two methods are actually local hooks. You can check when they will be executed in the [Request Lifecycle](../request_lifecycle) section.
43 changes: 43 additions & 0 deletions .website/overview/shelf_interop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Shelf Interoperability

Shelf is a low-level web server library for Dart. It allows you to handle HTTP requests and responses directly. Shelf is also the most popular web server library for Dart and has a large ecosystem of plugins and middleware ready to use.

For this particular reason and to make Serinus more flexible, we have decided to make Serinus compatible with Shelf. This means that you can use Shelf plugins and middleware in your Serinus applications.

## Usage

To use the Shelf Middlewares or Handlers in your Serinus application, you can use the `Middleware` class.
The class has a factory constructor called `Middleware.shelf` that takes a `shelf.Middleware` or a `shelf.Handler` and returns a Serinus Middleware that can be used in your application.

The `Middleware.shelf` factory constructor allows also to pass a `routes` parameter that is a list of routes where the middleware will be applied.

### Example

```dart
import 'package:serinus/serinus.dart';
import 'package:shelf/shelf.dart' as shelf;
final handler = (req) => shelf.Response.ok('Hello world from shelf');
class AppModule extends Module {
AppModule() : super(
imports: [],
controllers: [],
providers: [],
middlewares: [
Middleware.shelf(handler)
]
);
}
```

In the example above, we are using a Shelf Handler to return a simple response. We are wrapping the Shelf Handler with the `Middleware.shelf` factory constructor to create a Serinus Middleware that can be used in the application.

::: warning
If the handler returns a response with a body then Serinus will not execute the next middleware in the chain and the request will be completed.
:::

## Conclusion

Thanks to the interoperability you can now use existing Shelf plugins and middleware in your Serinus applications increasing the capabilities of them to a new level.
1 change: 1 addition & 0 deletions .website/plugins/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ This is a list of plugins that are available for Serinus. If you would like to a
- [Serve Static Files](/plugins/serve_static)
- [CORS](/plugins/cors)
- [Rate Limiter](/plugins/rate_limiter)
- [Swagger](/plugins/swagger/)
Loading

0 comments on commit edfb04b

Please sign in to comment.