Skip to content

gisila_doc (OpenAPI)

gisila_doc is the OpenAPI-aware variant of the gisila framework. You write a controller class with @Controller, @Get, @Post and friends, run build_runner, and get a generated attachToApp(app, router, spec) extension method that does two things at once:

  • registers every route on a shelf_router Router through gisila’s gisilaRoute(...), so each request runs through the normal gisila pipeline (rate limits, timeouts, auth guards, error mapping, services, forms);
  • adds the matching operation, JSON schemas and tags to an OpenApiSpec.

A bundled docsHandler serves the document as /openapi.json with Swagger UI at /docs and Redoc at /redoc.

The package re-exports the gisila runtime, so one import is enough: import 'package:gisila_doc/gisila_doc.dart';.

pubspec.yaml
dependencies:
gisila_doc: ^0.3.1
shelf: ^1.4.1
shelf_router: ^1.1.4
dev_dependencies:
build_runner: ^2.5.0

gisila_doc 0.3.1 works with gisila >=0.3.0 <0.5.0. The generator applies itself to any package that depends on gisila_doc (auto_apply: dependents), so no build.yaml is needed.

lib/controllers/users_controller.dart
import 'package:gisila_doc/gisila_doc.dart';
import '../models/user.dart';
import '../services/user_service.dart';
part 'users_controller.g.dart';
@Controller('/users', ['Users'])
class UsersController {
@Get('/', summary: 'List users')
Future<List<User>> listUsers(UserService users, {int? limit, int? offset}) =>
users.list(limit: limit, offset: offset);
@Get('/{id}', summary: 'Fetch a user', operationId: 'getUserById')
@ApiResponse(404, description: 'User not found')
Future<User> getUser(String id, UserService users) => users.getById(id);
}
bin/server.dart
import 'package:gisila_doc/gisila_doc.dart';
import 'package:my_app/controllers/users_controller.dart';
import 'package:my_app/services/user_service.dart';
Future<void> main() async {
final spec = OpenApiSpec(
info: const ApiInfo(title: 'Demo API', version: '1.0.0'),
);
final app = GisilaApp(config: AppConfig());
app.registerService<UserService>(UserService.new);
app.registerController(attacher: (app, router, {String prefix = ''}) {
UsersController().attachToApp(app, router, spec, prefix: prefix);
router.mount('/', docsHandler(spec)); // /openapi.json, /docs, /redoc
});
await app.start(port: 8080);
}
8080/docs
dart run build_runner build
dart run bin/server.dart

The path parameter id, the optional query parameters limit and offset, the User response schema, the 200 and 404 responses and a 400 for bad input all come from the method signatures and annotations.

  • You are building a JSON API on gisila and want an OpenAPI document that cannot drift from the code, because both are generated from the same annotations.
  • You want Swagger UI or Redoc for your team or API consumers without writing YAML.
  • You want to generate typed clients (TypeScript, Dart, Kotlin, …) from a spec.
  • Your app serves HTML or is otherwise not a documented HTTP API. Use plain gisila; its generator is smaller and its annotations have fewer options.
  • You need OpenAPI features the generator does not emit (callbacks, links, examples per media type, OAuth flows, non-JSON response content types). You can still add them through OpenApiSpec.extra, but at that point a hand-written spec may be simpler.

See gisila_doc or gisila? for the full trade-off.

Concepts

Guides