sirius_backend 2.1.3
sirius_backend: ^2.1.3 copied to clipboard
A powerful Dart backend framework for building scalable APIs.
Sirius โก โ A Lightweight Dart Backend Framework #
Sirius is a lightweight, expressive, and fast HTTP & WebSocket backend framework built entirely with Dart.
It features powerful routing, composable middleware, validation, and wrapper lifecycle hooks
๐ Features #
- โก Simple, expressive routing (GET, POST, PUT, PATCH, DELETE)
- ๐ Middleware support (before & after)
- ๐งฑ Wrapper middleware
.wrap()for lifecycle-level logic (timing, logging, etc.) - ๐ Grouped routes
- ๐ Validation with nested objects and list support
- ๐ WebSocket routing support
- ๐ก
dart:iobased performance
๐ฆ Installation #
dependencies:
sirius_backend: ^2.1.3
Then run:
dart pub get
๐ ๏ธ Basic Usage #
import 'package:sirius_backend/sirius_backend.dart';
void main() async {
final sirius = Sirius();
sirius.get('/hello', (req) async {
return Response.send({'message': 'Hello from Sirius!'});
});
await sirius.start(port: 3000);
}
๐ Routing #
sirius.get('/users', userController.getUsersHandler);
sirius.post('/users', userController.createUserHandler);
sirius.put('/users/:id', userController.updateUserHandler);
sirius.delete('/users/:id', userController.deleteUserHandler);
Grouped Routes #
sirius.group('/api', (router) {
router.get('/status', (req) async => Response.send({'ok': true}));
});
๐งฉ Middleware #
Global Middleware #
sirius.useBefore(AuthMiddleware());
sirius.useAfter(LoggerMiddleware());
Route Middleware #
sirius.get('/profile', (req) async => Response.send('Profile'),
useBefore: [AuthMiddleware()],
useAfter: [LoggerMiddleware()],
);
Example Middleware #
class AuthMiddleware extends Middleware {
@override
Future<Response> handle(Request request) async {
final token = request.headerValue('authorization');
if (token == 'valid-token') {
request.passData = {'userId': 123};
return Response.next();
}
return Response.send({'error': 'Unauthorized'}, statusCode: 401);
}
}
๐ Wrapper Middleware (NEW in 2.0) #
Wrappers allow full control around the lifecycle of a route.
class TimerWrapper extends Wrapper {
@override
Future<Response> handle(Request request, Future<Response> Function() nextHandler) async {
final start = DateTime.now();
final response = await nextHandler();
final end = DateTime.now();
print("Duration: ${end.difference(start)}");
return response;
}
}
Register wrapper globally:
sirius.wrap(TimerWrapper());
Or for a single route:
sirius.get('/dashboard', controller.dashboardHandler, wrap: [TimerWrapper()]);
๐งพ Request Object #
final id = request.pathVariable('id');
final name = request.jsonValue('name');
final headers = request.headers;
final method = request.method;
final userData = request.receiveData; // Passed via middleware
๐งญ Request Lifecycle Flow #
Incoming Request
โโโ Global Wrapper (Entry)
โโโ Route Wrapper (Entry)
โโโ Global Before Middleware(s)
โโโ Route Before Middleware(s)
โโโ Route Handler
โโโ Route After Middleware(s)
โโโ Global After Middleware(s)
โโโ Route Wrapper (Exit)
โโโ Global Wrapper (Exit)
โโโ Response Sent
โ Validation #
Basic Validation #
final validator = Validator(request.getAllFields, {
'name': ValidationRules(required: required(message: "Name is required")),
'age': ValidationRules(minNumber: minNumber(18)),
});
if (!validator.validate()) {
return Response.send(validator.getAllErrors, statusCode: 400);
}
Nested Object Validation #
'address': ValidationRules(
dataType: dataType(DataTypes.MAP),
childMap: {
'street': ValidationRules(required: required()),
'zip': ValidationRules(minLength: minLength(5)),
},
)
List Validation #
'items': ValidationRules(
dataType: dataType(DataTypes.LIST),
childList: [
ValidationRules(required: required(message: "Item is required")),
],
)
Validate Every List Element with Same Rules #
'ids': ValidationRules(
dataType: dataType(DataTypes.LIST),
childList: ValidationRules(
required: required(),
dataType: dataType(DataTypes.NUMBER),
).forEachElement(),
)
๐ค Response API #
return Response.send({"message": "Success"});
return Response.send({"error": "Unauthorized"}, statusCode: 401);
return Response.sendJson({"error": "Unauthorized"}, statusCode: 401);
return Response.next(); // To continue in middleware/chain
You can also override headers:
return Response.send({'ok': true}, overrideHeaders: (headers) {
headers.set('x-powered-by', 'Sirius');
});
๐ WebSocket Support #
sirius.webSocket('/chat', (request, socketConn) {
final connId = socketConn.getId;
print("Client connected: $connId");
// Respond to a custom event
socketConn.onEvent("ping", (data) {
print("Received ping: $data");
socketConn.sendEvent("pong", {"message": "Pong received!", "echo": data});
});
// Listen to raw messages (not event-based)
socketConn.onData((msg) {
print("Raw message: $msg");
socketConn.sendData("Echo: $msg");
});
// Handle disconnection
socketConn.onDisconnect(() {
print("Client disconnected: $connId");
});
});
๐งฑ Advanced Usage: Route Composition #
sirius.get('/secure-data',
secureDataHandler,
useBefore: [AuthMiddleware()],
useAfter: [LoggerMiddleware()],
wrap: [TimerWrapper()],
);
๐ License #
MIT License โ free for commercial and personal use.
๐ค Contributing #
Pull requests, issues, and feature suggestions are welcome. Let's make backend dev in Dart delightful!