Metadata
Metadata are used to add information to a class, a method, a property, or a parameter. In other programming languages they are easily accessible thanks to reflaction. But since they are really useful, Serinus provides his own way to add metadata to your routes and controllers.

INFO
Dart does not support reflection, so Serinus provides a more static way to add metadata to your classes.
Creating Metadata
To create a metadata, you need to extend the Metadata
class. As simple as that.
import 'package:serinus/serinus.dart';
class IsPublic extends Metadata {
const IsPublic(): super(
name: 'IsPublic',
value: true
);
}
As you can see, the Metadata
class requires a name
and a value
parameter. The name
is the name of the metadata, and the value
is the value of the metadata. You can use any type of value you want.
Also, since Serinus uses a Context
to store the request information, you can access it using a ContextualizedMetadata.
import 'package:serinus/serinus.dart';
class IsPublic extends ContextualizedMetadata {
const IsPublic(): super(
name: 'IsPublic',
value: (context) async => context.query['public'] == 'true'
);
}
In this case, the value
is a function that returns a Future<bool>
. This is useful when you need to access the RequestContext
to get some information.
Using Metadata
Now we can use the metadata in our controllers or routes.
If you add a metadata to a controller, it will be applied to all the routes of the controller. If you add a metadata to a route, it will be applied only to that specific route. Pretty cool, right?
import 'package:serinus/serinus.dart';
class UserController extends Controller {
UserController(): super(path: '/users') {
on(Route.get('/'), getUsers, metadata: [IsPublic()]);
on(Route.get('/<id>'), getUser);
}
Future<List<User>> getUsers(RequestContext context) async {
final users = await context.use<UsersService>().getUsers();
return users;
}
}
In this case, the IsPublic
metadata will be applied only to the /users
route. This means that if we have an Hook or a Middleware that checks if the user is authenticated, we can skip it for this route.
Accessing Metadata
How we can access the metadata? It's really simple.
You can access them using two methods in the RequestContext
object: stat
and canStat
.
The first one will return the metadata if it's present, otherwise it will throw a StateError. The second one will only return if the metadata is present or not. They can be used in combination in this way:
import 'package:serinus/serinus.dart';
class UserController extends Controller {
UserController(): super(path: '/users') {
on(Route.get('/'), getUsers, metadata: [IsPublic()]);
on(Route.get('/<id>'), getUser);
}
Future<List<User>> getUsers(RequestContext context) async {
if (context.canStat('IsPublic')) {
// Do something
}
final users = await context.use<UsersService>().getUsers();
return users;
}
}
In this case, we check if the IsPublic
metadata is present in the route. If it is, we can do something special. Otherwise, we can continue with the normal flow.