toOpenApiSpec method
Generates an OpenAPI 3.1 specification map from all registered routes.
Converts parameterized path patterns (/api/tasks/:id -> /api/tasks/{id}),
extracts path parameters, infers tags from URL segments, and configures JSON request/response schemas.
Returns a standard OpenAPI 3.1.0 compliant Map.
Implementation
Map<String, dynamic> toOpenApiSpec({
String title = 'Bloom API',
String version = '1.0.0',
String description = 'Full-stack Bloom Server API',
}) {
final paths = <String, Map<String, dynamic>>{};
for (final route in _routes) {
if (route.method == '*' || route.pathPattern.isEmpty) continue;
if (route.pathPattern.startsWith('/api/openapi') ||
route.pathPattern.startsWith('/api/docs') ||
route.pathPattern.startsWith('/api/swagger') ||
route.pathPattern == '/' ||
route.pathPattern.endsWith('.js') ||
route.pathPattern.endsWith('.json')) {
continue;
}
// Convert /api/tasks/:id to /api/tasks/{id}
var openApiPath = route.pathPattern;
for (final param in route.paramNames) {
openApiPath = openApiPath.replaceAll(':$param', '{$param}');
}
final methodLower = route.method.toLowerCase();
paths.putIfAbsent(openApiPath, () => <String, dynamic>{});
// Derive tag from path segment (e.g. /api/tasks -> Tasks)
final segments = openApiPath
.split('/')
.where((s) => s.isNotEmpty && s != 'api')
.toList();
final tag = segments.isNotEmpty
? segments.first.substring(0, 1).toUpperCase() +
segments.first.substring(1)
: 'General';
final operation = <String, dynamic>{
'tags': [tag],
'summary': '${route.method} $openApiPath',
'responses': {
'200': {'description': 'Successful response'},
},
};
if (route.paramNames.isNotEmpty) {
operation['parameters'] = route.paramNames
.map((p) => {
'name': p,
'in': 'path',
'required': true,
'schema': {'type': 'string'},
})
.toList();
}
if (methodLower == 'post' ||
methodLower == 'put' ||
methodLower == 'patch') {
operation['requestBody'] = {
'required': true,
'content': {
'application/json': {
'schema': {'type': 'object'},
},
},
};
}
paths[openApiPath]![methodLower] = operation;
}
return {
'openapi': '3.1.0',
'info': {
'title': title,
'version': version,
'description': description,
},
'paths': paths,
};
}