MasterController

OpenAPI

An OpenAPI 3.1 document and Swagger UI, generated from what the app already declares.

master.useOpenApi() is ASP.NET Core’s AddOpenApi() / MapOpenApi() plus a Swagger UI page. The document is derived from routes, typed constraints, static schemas, authorize, registered auth schemes, and output-cache policies — there is nothing to keep in sync by hand.

Setup#

server.js
const server = master.setupServer('http');
master.useOpenApi({
  path: '/openapi.json',                 // default
  ui: '/docs',                           // Swagger UI page (true = '/docs', false = none); CDN-loaded in the browser
  title: 'Items API', version: '2.0.0', description: '…',
  servers: [{ url: 'https://api.example.com' }],
  filter: ({ controller }) => controller !== 'internal',   // hide routes
  transform: (doc) => doc,                                // last-chance edits
});
await master.start(server);
master.openApi.document();               // the object, e.g. for tests or a build step

Options: path, ui, title, version, description, servers, tags, filter, transform. Open /docs in a browser for the interactive UI, or fetch /openapi.json for tooling.

What is derived#

SourceOpenAPI
router.route('/items/:id(int)', 'items#show', 'get')paths['/items/{id}'].get, path parameter id: integer; operationId: items_show, tags: ['items']
router.resources('tags', { only })the REST operations
static schemas = { create: { body, query, headers, route } }requestBody (JSON Schema from the validation rules), query/header/path parameters, 400 ValidationProblemDetails
route { authorize } / static authorize / { allowAnonymous }security: [{ bearer: ['role:admin', 'policy:Senior'] }], 401/403 ProblemDetails; anonymous → security: []
master.auth.addJwtBearer / addCookie / customcomponents.securitySchemes (http bearer JWT, apiKey cookie, apiKey header)
static openapi = { action: { summary, description, tags, responses, deprecated, operationId } }operation metadata (responses values: a string description or a full response object)
{ outputCache }x-output-cache extension
master.map.get(...) minimal APIsdocumented like controller routes, under the minimal tag

Rules → JSON Schema#

string (minLength/maxLength/pattern), email/url/uuid/date/datetime (formats), number/integer (minimum/maximum), boolean, array (items/minItems/maxItems), object (properties/required), enum, default, nullable. See Model Binding for the rule set.

Customizing#

Per-operation metadata lives next to the action in static openapi; the openapi option does the same for minimal APIs.

itemsController.js
export default class ItemsController {
  static schemas = {
    create: { body: { name: 'string!', price: { type: 'number', min: 0 } } },
    index:  { query: { page: { type: 'integer', default: 1, min: 1 } } },
  };
  static authorize = { '*': true, index: false, show: false };

  // operation metadata — the equivalent of [EndpointSummary] / [ProducesResponseType]
  static openapi = {
    create: { summary: 'Create an item', tags: ['catalog'], responses: { 201: 'Created', 409: 'Duplicate name' } },
    index:  { summary: 'List items', deprecated: false, operationId: 'listItems' },
    show:   { responses: { 200: { description: 'The item', content: { 'application/json': { schema: { $ref: '#/components/schemas/Item' } } } } } },
  };
}

filter drops routes from the document; transform receives the finished document for last-chance edits — add shared component schemas, contact info, or anything the generator does not know about.

javascript
master.useOpenApi({
  title: 'Items API', version: '2.0.0',
  transform: (doc) => {
    doc.components.schemas.Item = { type: 'object', properties: { id: { type: 'integer' }, name: { type: 'string' } } };
    doc.info.contact = { email: 'api@example.com' };
    return doc;
  },
});

// regenerate after runtime changes (e.g. routes mapped after start)
master.openApi.invalidate();
Swagger UI assets
The UI page loads Swagger UI from a CDN in the browser; the JSON document itself is served by your app. Set ui: false if your CSP forbids external scripts and point your own UI at /openapi.json.